docs: clean
This commit is contained in:
7 files changed
+1
-258
No files matched your search
@@ -1,11 +0,0 @@
|
||||
Architecture
|
||||
============
|
||||
|
||||
The Workflow
|
||||
------------
|
||||

|
||||
|
||||
The business Entities
|
||||
---------------------
|
||||
|
||||

|
||||
@@ -1,67 +0,0 @@
|
||||
# Exemple de structure
|
||||
|
||||
Les couches, du plus interne au plus externe
|
||||
```
|
||||
Domain (le cœur, ne dépend de RIEN d'externe)
|
||||
↑
|
||||
Application (orchestre le Domain, ne connaît pas l'infra concrète)
|
||||
↑
|
||||
Infrastructure (WebSocket, DB, event store — dépend de tout le reste)
|
||||
```
|
||||
|
||||
```
|
||||
src/
|
||||
└── contexts/
|
||||
├── auth/
|
||||
└── ...
|
||||
└── game/
|
||||
├── domain/ ← Le cœur métier, zéro dépendance externe
|
||||
│ ├── game/
|
||||
│ │ ├── Game.ts ← Aggregate Root
|
||||
│ │ ├── Player.ts ← Entity interne
|
||||
│ │ ├── Card.ts ← Entity
|
||||
│ │ ├── Color.ts ← Value Object
|
||||
│ │ ├── Deck.ts ← VO ou petite structure
|
||||
│ │ └── errors/
|
||||
│ │ ├── InvalidMoveError.ts
|
||||
│ │ └── ColorChoiceRequiredError.ts
|
||||
│ └── events/ ← Events de DOMAINE (internes)
|
||||
│ ├── CardPlayed.ts
|
||||
│ ├── CardDrawn.ts
|
||||
│ ├── TurnPassed.ts
|
||||
│ └── DomainEvent.ts ← interface/type de base
|
||||
├── application/ ← Orchestration, cas d'usage
|
||||
│ ├── commands/ ← Les Commandes (intentions)
|
||||
│ │ ├── PlayCardCommand.ts
|
||||
│ │ └── DrawCardCommand.ts
|
||||
│ ├── handlers/ ← Un handler par commande
|
||||
│ │ ├── PlayCardHandler.ts ← charge l'aggregate, appelle game.playCard(), save
|
||||
│ │ └── DrawCardHandler.ts
|
||||
│ ├── projections/ ← LA LOGIQUE de construction des projections
|
||||
│ │ ├── GameSummaryProjector.kt ← écoute les events, met à jour la vue
|
||||
│ │ └── PlayerStatsProjector.kt
|
||||
│ └── ports/ ← INTERFACES seulement (le "hexagone")
|
||||
│ ├── GameRepository.ts ← interface, pas d'implémentation
|
||||
│ ├── EventPublisher.ts ← interface, pas d'implémentation
|
||||
│ └── ProjectionStore.kt ← interface, où lire/écrire la projection
|
||||
├── infrastructure/ ← Tout ce qui est technique/externe
|
||||
│ ├── persistence/
|
||||
│ │ ├── EventStoreGameRepository.ts ← implémente GameRepository
|
||||
│ │ ├── EventStore.ts
|
||||
│ │ ├── projections/
|
||||
│ │ │ ├── GameSummaryProjectionStore.kt ← implémentation concrète (DB, table dédiée)
|
||||
│ │ │ └── models/
|
||||
│ │ │ └── GameSummaryView.kt ← structure de la vue elle-même
|
||||
│ ├── websocket/
|
||||
│ │ ├── WebSocketServer.ts
|
||||
│ │ ├── connectionManager.ts ← Map<gameId, Map<playerId, WebSocket>>
|
||||
│ │ └── commandRouter.ts ← reçoit le message brut, dispatch vers le bon handler
|
||||
│ └── eventPublisher/
|
||||
│ └── WebSocketEventPublisher.ts ← implémente EventPublisher, fait le broadcast
|
||||
└── presentation/ ← Traduction vers/depuis le client (le fameux DTO layer)
|
||||
├── clientEvents/
|
||||
│ ├── ClientEvent.ts ← types des events envoyés au front
|
||||
│ └── toClientEvent.ts ← fonction de traduction domain event → client event
|
||||
└── clientCommands/
|
||||
└── parseIncomingCommand.ts ← valide/parse le message brut du client → Command
|
||||
```
|
||||
+1
-1
@@ -23,7 +23,7 @@ Api url:
|
||||
- [Backend API](http://api.traefik.me/)
|
||||
- [Frontend web site](http://app.traefik.me/) (WIP)
|
||||
|
||||
Exposed url on test env:
|
||||
Exposed url on dev env:
|
||||
- [PostgreSql](http://localhost:5432/)
|
||||
- [Redis](http://localhost:6379/)
|
||||
- [RabbitMQ](http://localhost:15672/)
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
@startuml
|
||||
'https://plantuml.com/class-diagram
|
||||
|
||||
left to right direction
|
||||
|
||||
class GameList <<Projection>> {
|
||||
+ status: Status
|
||||
}
|
||||
class GameState <<Projection>> {
|
||||
+ players: List<Player>
|
||||
+ currentPlayerTurn: Player
|
||||
+ lastCardPlayer: Player
|
||||
+ colorOnCurrentStack: Color
|
||||
+ direction: Direction
|
||||
+ readyPlayers: List<Player>
|
||||
+ deck: Deck
|
||||
+ isStarted: Boolean
|
||||
+ playerWins: List<Player>
|
||||
}
|
||||
interface Card {
|
||||
+ id: UUID
|
||||
}
|
||||
enum Color {
|
||||
+ Blue
|
||||
+ Red
|
||||
+ Yellow
|
||||
+ Green
|
||||
}
|
||||
class GameId {
|
||||
+ id: UUID
|
||||
}
|
||||
class Player {
|
||||
+ id: PlayerId
|
||||
+ name: String
|
||||
}
|
||||
class Deck {
|
||||
+ stack: Stack
|
||||
+ discard: Discard
|
||||
+ playersHands: PlayersHands
|
||||
}
|
||||
class Stack {
|
||||
+ cards: List<Card>
|
||||
+ shuffle()
|
||||
}
|
||||
class Discard {
|
||||
+ cards: List<Card>
|
||||
}
|
||||
class PlayerHands {
|
||||
+ map: Map<PlayerId, List<Card>>
|
||||
}
|
||||
|
||||
class NumericCard {
|
||||
+ number: Int
|
||||
+ color: Color
|
||||
}
|
||||
class ReverseCard {
|
||||
+ color: Color
|
||||
}
|
||||
class PassCard {
|
||||
+ color: Color
|
||||
}
|
||||
class Plus2Card {
|
||||
+ color: Color
|
||||
}
|
||||
class Plus4Card
|
||||
class ChangeColorCard
|
||||
|
||||
GameState *-- Deck
|
||||
GameState o-- "many" Player
|
||||
Deck *-- PlayerHands
|
||||
PlayerHands *-- "many" Card
|
||||
PlayerHands o-- "many" Player
|
||||
Stack *-- "many" Card
|
||||
Discard *-- "many" Card
|
||||
Deck *-- Stack
|
||||
Deck *-- Discard
|
||||
GameState *-- GameId
|
||||
Card <|--- NumericCard
|
||||
Card <|--- ReverseCard
|
||||
Card <|--- PassCard
|
||||
Card <|--- ChangeColorCard
|
||||
Card <|--- Plus2Card
|
||||
Card <|--- Plus4Card
|
||||
|
||||
ReverseCard o-- Color
|
||||
NumericCard o-- Color
|
||||
PassCard o-- Color
|
||||
Plus2Card o-- Color
|
||||
|
||||
GameList *-- GameId
|
||||
GameList o-- "many" Player
|
||||
|
||||
@enduml
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="668px" preserveAspectRatio="none" style="width:1329px;height:668px;" version="1.1" viewBox="0 0 1329 668" width="1329px" zoomAndPan="magnify"><defs/><g><!--class GameList--><g id="elem_GameList"><rect codeLine="5" fill="#F1F1F1" height="79.2031" id="GameList" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="110.8203" x="50.5" y="7"/><ellipse cx="72.7501" cy="29.291" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M75.5157,25.166 Q75.672,24.9473 75.8595,24.8379 Q76.047,24.7285 76.2657,24.7285 Q76.6407,24.7285 76.8751,24.9941 Q77.1095,25.2441 77.1095,25.8535 L77.1095,27.3066 Q77.1095,27.916 76.8751,28.1816 Q76.6407,28.4473 76.2657,28.4473 Q75.922,28.4473 75.7188,28.2441 Q75.5157,28.0566 75.4063,27.541 Q75.3595,27.1816 75.172,26.9941 Q74.8438,26.6191 74.2345,26.4004 Q73.6251,26.1816 73.0001,26.1816 Q72.2345,26.1816 71.5938,26.5098 Q70.9688,26.8379 70.4688,27.5879 Q69.9845,28.3379 69.9845,29.3691 L69.9845,30.4629 Q69.9845,31.6973 70.8751,32.5254 Q71.7657,33.3379 73.3595,33.3379 Q74.297,33.3379 74.9532,33.0879 Q75.3438,32.9316 75.7657,32.4941 Q76.0313,32.2285 76.172,32.1504 Q76.3282,32.0723 76.5313,32.0723 Q76.8595,32.0723 77.1095,32.3379 Q77.3751,32.5879 77.3751,32.9316 Q77.3751,33.2754 77.0313,33.6816 Q76.5313,34.2598 75.7345,34.5879 Q74.6563,35.041 73.3595,35.041 Q71.8438,35.041 70.6407,34.416 Q69.6563,33.916 68.9688,32.8535 Q68.2813,31.7754 68.2813,30.4941 L68.2813,29.3379 Q68.2813,28.0098 68.8907,26.8691 Q69.5157,25.7129 70.6095,25.1035 Q71.7032,24.4785 72.9376,24.4785 Q73.672,24.4785 74.3126,24.6504 Q74.9688,24.8066 75.5157,25.166 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="66.709" x="86.3612" y="24.9492">«Projection»</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="59.9102" x="89.7606" y="43.0684">GameList</text><line style="stroke:#181818;stroke-width:0.5;" x1="51.5" x2="160.3203" y1="51.582" y2="51.582"/><ellipse cx="61.5" cy="66.3926" fill="none" rx="3" ry="3" style="stroke:#038048;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="84.8203" x="70.5" y="70.6895">status: Status</text><line style="stroke:#181818;stroke-width:0.5;" x1="51.5" x2="160.3203" y1="78.2031" y2="78.2031"/></g><!--class GameState--><g id="elem_GameState"><rect codeLine="8" fill="#F1F1F1" height="228.1719" id="GameState" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="197.9512" x="7" y="121.5"/><ellipse cx="66.3188" cy="143.791" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M69.0845,139.666 Q69.2407,139.4473 69.4282,139.3379 Q69.6157,139.2285 69.8345,139.2285 Q70.2095,139.2285 70.4438,139.4941 Q70.6782,139.7441 70.6782,140.3535 L70.6782,141.8066 Q70.6782,142.416 70.4438,142.6816 Q70.2095,142.9473 69.8345,142.9473 Q69.4907,142.9473 69.2876,142.7441 Q69.0845,142.5566 68.9751,142.041 Q68.9282,141.6816 68.7407,141.4941 Q68.4126,141.1191 67.8032,140.9004 Q67.1938,140.6816 66.5688,140.6816 Q65.8032,140.6816 65.1626,141.0098 Q64.5376,141.3379 64.0376,142.0879 Q63.5532,142.8379 63.5532,143.8691 L63.5532,144.9629 Q63.5532,146.1973 64.4438,147.0254 Q65.3345,147.8379 66.9282,147.8379 Q67.8657,147.8379 68.522,147.5879 Q68.9126,147.4316 69.3345,146.9941 Q69.6001,146.7285 69.7407,146.6504 Q69.897,146.5723 70.1001,146.5723 Q70.4282,146.5723 70.6782,146.8379 Q70.9438,147.0879 70.9438,147.4316 Q70.9438,147.7754 70.6001,148.1816 Q70.1001,148.7598 69.3032,149.0879 Q68.2251,149.541 66.9282,149.541 Q65.4126,149.541 64.2095,148.916 Q63.2251,148.416 62.5376,147.3535 Q61.8501,146.2754 61.8501,144.9941 L61.8501,143.8379 Q61.8501,142.5098 62.4595,141.3691 Q63.0845,140.2129 64.1782,139.6035 Q65.272,138.9785 66.5063,138.9785 Q67.2407,138.9785 67.8813,139.1504 Q68.5376,139.3066 69.0845,139.666 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="66.709" x="88.8711" y="139.4492">«Projection»</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="70.8135" x="86.8188" y="157.5684">GameState</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="203.9512" y1="166.082" y2="166.082"/><ellipse cx="18" cy="180.8926" fill="none" rx="3" ry="3" style="stroke:#038048;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="130.7305" x="27" y="185.1895">players: List<Player></text><ellipse cx="18" cy="199.5137" fill="none" rx="3" ry="3" style="stroke:#038048;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="159.5029" x="27" y="203.8105">currentPlayerTurn: PlayerLine truncated
|
||||
|
Before Width: | Height: | Size: 48 KiB |
@@ -1,84 +0,0 @@
|
||||
@startuml
|
||||
'https://plantuml.com/use-case-diagram
|
||||
|
||||
package Legend {
|
||||
usecase (Queries) #7693C4
|
||||
usecase (Projections) #AB64C9
|
||||
usecase (Events) #5FAD56
|
||||
}
|
||||
|
||||
actor User
|
||||
entity Query #7693C4
|
||||
|
||||
entity Command #5FAD56
|
||||
entity Event #5FAD56
|
||||
entity Projection #AB64C9
|
||||
|
||||
database Postgresql
|
||||
database Redis
|
||||
queue RabbitMQ
|
||||
|
||||
usecase (Web socket adapter) #5FAD56
|
||||
usecase (Command handler) #5FAD56
|
||||
usecase/ (Action) #5FAD56
|
||||
usecase (Event handler) #5FAD56
|
||||
usecase (Version builder) #5FAD56
|
||||
usecase (Event store) #5FAD56
|
||||
usecase (Event stream) #5FAD56
|
||||
usecase (Event bus) #5FAD56
|
||||
usecase/ (Reaction listener) #5FAD56
|
||||
|
||||
usecase/ (Projection builder) #AB64C9
|
||||
usecase (Projection repository) #AB64C9
|
||||
usecase (Projection bus) #AB64C9
|
||||
|
||||
usecase (Controller) #7693C4
|
||||
|
||||
User -> Query : <<create>>
|
||||
Command <- User : <<create>>
|
||||
User ---> (Controller) : Get \nprojection
|
||||
User <-- (Controller) : Returns \nprojection
|
||||
|
||||
(Controller) --------> (Projection repository) : Get \nprojection
|
||||
|
||||
User -> (Web socket adapter) : Send \ncommand
|
||||
(Web socket adapter) --> (Command handler) : Send \ncommand
|
||||
(Web socket adapter) ...> User : Send notification \n(error or success)
|
||||
|
||||
(Command handler) ..> (Web socket adapter) : Send \nnotification
|
||||
(Command handler) -> (Action) : Execute action
|
||||
(Command handler) <- (Action) : Returns \nevent builder
|
||||
(Command handler) ---> (Event handler) : Dispatch \nevent \n(send an event builder)
|
||||
(Command handler) --> Event : <<Create>>
|
||||
|
||||
(Event handler) --> (Event store) : Publish \nevent
|
||||
(Event handler) <-- (Reaction listener) : Dispatch \n new event
|
||||
(Version builder) <- (Event handler) : build next version
|
||||
note "Acquire a lock, \nget the next event version, \nand then, build the event " as EventHandlerNote
|
||||
EventHandlerNote <-- (Event handler)
|
||||
|
||||
(Event store) -left-> (Event stream)
|
||||
(Event store) ---> (Event bus) : Publish \nevent
|
||||
|
||||
(Event stream) --> Postgresql : Persist \nevent
|
||||
(Event bus) -> RabbitMQ : Publish \nevent
|
||||
(Event bus) -> RabbitMQ : Subscribe \nto event
|
||||
(Event bus) <. RabbitMQ : Emit event
|
||||
|
||||
(Reaction listener) ---> (Projection bus) : Subscribe
|
||||
(Reaction listener) <.. (Projection bus) : Emit projection
|
||||
|
||||
(Projection bus) <- (Projection repository) : Publish \nprojection
|
||||
RabbitMQ <- (Projection bus) : Publish \nprojection
|
||||
RabbitMQ <- (Projection bus) : Subscribe \nto projection
|
||||
RabbitMQ .> (Projection bus) : Emit projection
|
||||
|
||||
(Event bus) <---- (Projection repository) : Subscribe
|
||||
(Event bus) ..> (Projection repository) : Emit event
|
||||
|
||||
(Projection repository) --> Redis : Persist \nprojection
|
||||
(Projection repository) <- Redis : Get \nprojection
|
||||
(Projection repository) -> (Projection builder) : Build \nprojection
|
||||
|
||||
(Projection builder) --> Projection : <<create projection>>
|
||||
@enduml
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="1460px" preserveAspectRatio="none" style="width:1185px;height:1460px;" version="1.1" viewBox="0 0 1185 1460" width="1185px" zoomAndPan="magnify"><defs/><g><!--cluster Legend--><g id="cluster_Legend"><path d="M897,6.0137 L947.7793,6.0137 A3.75,3.75 0 0 1 950.2793,8.5137 L957.2793,30.6348 L1176,30.6348 A2.5,2.5 0 0 1 1178.5,33.1348 L1178.5,207.5137 A2.5,2.5 0 0 1 1176,210.0137 L897,210.0137 A2.5,2.5 0 0 1 894.5,207.5137 L894.5,8.5137 A2.5,2.5 0 0 1 897,6.0137 " fill="none" style="stroke:#000000;stroke-width:1.5;"/><line style="stroke:#000000;stroke-width:1.5;" x1="894.5" x2="957.2793" y1="30.6348" y2="30.6348"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="49.7793" x="898.5" y="23.1211">Legend</text></g><g id="elem_Queries"><ellipse cx="957.5879" cy="59.315" fill="#7693C4" rx="46.5879" ry="16.3013" style="stroke:#181818;stroke-width:0.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="49.0205" x="930.0776" y="64.1187">Queries</text></g><g id="elem_Projections"><ellipse cx="1100.6745" cy="59.4601" fill="#AB64C9" rx="61.6745" ry="16.4464" style="stroke:#181818;stroke-width:0.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="69.2549" x="1063.0471" y="64.2638">Projections</text></g><g id="elem_Events"><ellipse cx="957.4528" cy="178.2499" fill="#5FAD56" rx="41.9528" ry="16.2362" style="stroke:#181818;stroke-width:0.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="42.7998" x="933.2413" y="183.0022">Events</text></g><!--entity User--><g id="elem_User"><ellipse cx="605.2793" cy="28.5137" fill="#F1F1F1" rx="8" ry="8" style="stroke:#181818;stroke-width:0.5;"/><path d="M605.2793,36.5137 L605.2793,63.5137 M592.2793,44.5137 L618.2793,44.5137 M605.2793,63.5137 L592.2793,78.5137 M605.2793,63.5137 L618.2793,78.5137 " fill="none" style="stroke:#181818;stroke-width:0.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="29.5586" x="590.5" y="95.1211">User</text></g><!--entity Query--><g id="elem_Query"><ellipse cx="726.562" cy="50.0137" fill="#7693C4" rx="12" ry="12" style="stroke:#181818;stroke-width:0.5;"/><line style="stroke:#181818;stroke-width:0.5;" x1="714.562" x2="738.562" y1="64.0137" y2="64.0137"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="38.124" x="707.5" y="81.1211">Query</text></g><!--entity Command--><g id="elem_Command"><ellipse cx="471.2896" cy="50.0137" fill="#5FAD56" rx="12" ry="12" style="stroke:#181818;stroke-width:0.5;"/><line style="stroke:#181818;stroke-width:0.5;" x1="459.2896" x2="483.2896" y1="64.0137" y2="64.0137"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="64.5791" x="439" y="81.1211">Command</text></g><!--entity Event--><g id="elem_Event"><ellipse cx="243.3999" cy="530.5137" fill="#5FAD56" rx="12" ry="12" style="stroke:#181818;stroke-width:0.5;"/><line style="stroke:#181818;stroke-width:0.5;" x1="231.3999" x2="255.3999" y1="544.5137" y2="544.5137"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="35.7998" x="225.5" y="561.6211">Event</text></g><!--entity Projection--><g id="elem_Projection"><ellipse cx="750.6274" cy="1410.0137" fill="#AB64C9" rx="12" ry="12" style="stroke:#181818;stroke-width:0.5;"/><line style="stroke:#181818;stroke-width:0.5;" x1="738.6274" x2="762.6274" y1="1424.0137" y2="1424.0137"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="62.2549" x="719.5" y="1441.1211">Projection</text></g><!--entity Postgresql--><g id="elem_Postgresql"><path d="M83.5,905.0137 C83.5,895.0137 126.5723,895.0137 126.5723,895.0137 C126.5723,895.0137 169.6445,895.0137 169.6445,905.0137 L169.6445,932.6348 C169.6445,942.6348 126.5723,942.6348 126.5723,942.6348 C126.5723,942.6348 83.5,942.6348 83.5,932.6348 L83.5,905.0137 " fill="#F1F1F1" style="stroke:#181818;stroke-width:0.5;"/><path d="M83.5,905.0137 C83.5,915.0137 126.5723,915.0137 126.5723,915.0137 C126.5723,915.0137 169.6445,915.0137 169.6445,905.0137 " fill="none" style="stroke:#181818;stroke-width:0.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="66.1445" x="93.5" y="934.1211">Postgresql</text></g><!--entity Redis--><g id="elem_Redis"><path d="M462.5,1405.5137 C462.5,1395.5137 490.3965,1395.5137 490.3965,1395.5137 C490.3965,1395.5137 518.293,1395.5137 518.293,1405.5137 L518.293,1433.1348 C518.293,1443.1348 490.3965,1443.1348 490.3965,1443.1348 C490.3965,1443.1348 462.5,1443.1348 462.5,1433.1348 L462.5,1405.5137 " fill="#F1F1F1" style="stroke:#181818;stroke-width:0.5;"/><path d="M462.5,1405.5137 C462.5,1415.5137 490.3965,Line truncated
|
||||
|
Before Width: | Height: | Size: 35 KiB |
Reference in new issue
Block a user