From f1aecc7c19671a055d964d562df851a3725688c9 Mon Sep 17 00:00:00 2001 From: jgoteam Date: Wed, 24 Apr 2024 08:44:25 -0700 Subject: [PATCH 01/12] docs: doc edits Co-authored-by: Alex Sklar Co-authored-by: Erik Margetis --- docs/core-concepts/mutators.md | 9 ++--- docs/core-concepts/rooms.md | 7 ++-- docs/core-concepts/subscriptions.md | 6 ++-- docs/core-concepts/transactions.md | 26 +++++++++++--- .../add-to-existing-project.md | 28 +++++++-------- docs/getting-started/start-a-new-project.md | 34 +++++++++---------- docs/guides/analytics.md | 22 +++++++++--- docs/guides/authentication.md | 22 ++++++------ docs/guides/configuration.md | 2 +- docs/index.md | 6 ++-- 10 files changed, 96 insertions(+), 66 deletions(-) diff --git a/docs/core-concepts/mutators.md b/docs/core-concepts/mutators.md index ed0881e..c26d2a0 100644 --- a/docs/core-concepts/mutators.md +++ b/docs/core-concepts/mutators.md @@ -4,12 +4,13 @@ sidebar_position: 3 # Mutators -A **mutator** is a Javascript function, defined by the developer, that defines logic to transform the shared application state through a [transaction](https://syncosaurus.github.io/docs/core-concepts/transactions). A key feature of mutators is that *they run twice*: +A **mutator** is a Javascript function, defined by the developer, that transforms the shared application state through a [transaction](transactions.md). A key feature of mutators is that *they run twice*: -- Mutators are first run on the client against the client's local state, and the client's user interface updates immediately. The mutation does not wait for a server response. This is intentional, and is also vital in keeping the client's perceived response times low and the user experience smooth. Because these mutators have not yet been confirmed by the authoritative server, the mutations made by this first run of mutators are known as optimistic mutations.  -- Mutators are then run by the server against the server's state, which is the authoritative state. Although the defined mutators are the same, because the mutators are now run against the server's state instead of the client's state, the result of the mutation may be different. This occurrence is a normal part of the syncing process. When the server broadcasts its authoritative updates and if the client state with applied optimistic mutations is different than the authoritative state sent by the server, Syncosaurus will automatically roll back its applied optimistic mutations and apply updates to match the server's authoritative state. +- Mutators are first run on the client against the client's local state, and the client's user interface updates immediately. The mutation does not wait for a server response. This is intentional, and vital in keeping the client's perceived response times low and the user experience smooth. Because these mutators have not yet been confirmed by the authoritative server, the mutations made by this first run of mutators are known as *optimistic mutations*.  +- Mutators are then run by the server against the server's state, which is the authoritative state. Although the defined mutators are the same, because the mutators are now run against the server's state instead of the client's state, the result of the mutation may be different. This occurrence is a normal part of the syncing process. +- When the server broadcasts its authoritative updates and if the client state with applied optimistic mutations is different than the authoritative state sent by the server, Syncosaurus will automatically roll back its applied optimistic mutations and apply updates to match the server's authoritative state. -Because mutators are just high-level Javascript functions, the developer gains a high level of flexibility and control in how and when updates should be mutated. Mutators can be used to not only modify the shared state of a collaborative application. These mutators can also be used to selectively aggregate, merge, and/or delete different pieces of the shared state, as well as to implement custom application logic or fine-grained authorization. +Because mutators are Javascript functions, the developer gains a high level of flexibility and control in how and when updates should be mutated. Mutators can be used to modify the shared state of a collaborative application. They can also be used to selectively aggregate, merge, and/or delete different pieces of the shared state, as well as to implement custom application logic. The function `increment` below is an example of a mutator: diff --git a/docs/core-concepts/rooms.md b/docs/core-concepts/rooms.md index fe12a16..2582ea5 100644 --- a/docs/core-concepts/rooms.md +++ b/docs/core-concepts/rooms.md @@ -4,7 +4,9 @@ sidebar_position: 1 # Rooms -The primary unit of collaboration within a Syncosaurus application is the **room**, a central coordination point and data store location. Much like a physical meeting room may serve as a hub for multiple individuals to communicate and exchange information and ideas, a room in Syncosaurus serves as a hub for users of a collaborative application (known as *clients*) to share updates and access the same data. In both scenarios, any update sent by any individual within a room may be received by all individuals present within the room, and any individual in the room also has access to the room's shared data (assuming they have permission to do so.) As with an individual moving in the physical world, a client in a collaborative web application can also move between different rooms, which often has its own features and rules. The application developer is ultimately responsible for determining these room attributes and how they align with the attributes of clients entering, collaborating, and leaving those rooms. +The primary unit of collaboration within a Syncosaurus application is the **room**, a central coordination point and data store location. Much like a physical meeting room may serve as a hub for multiple individuals to communicate and exchange information and ideas, a room in Syncosaurus serves as a hub for users of a collaborative application (known as **clients**) to share updates and access the same data. In both scenarios, any update sent by any individual within a room may be received by all individuals present within the room, and any individual in the room also has access to the room's shared data (assuming they have permission to do so.) As with an individual moving in the physical world, a client in a collaborative web application can also move between different rooms, which often has its own features and rules. + +The application developer is ultimately responsible for defining these room attributes and how they align with the attributes of clients entering, collaborating, and leaving those rooms. Let's illustrate this idea with an example. Let's say we have an e-learning platform on which teachers can host lectures and discussions in different rooms. A music room could have a chord visualization feature, while a statistics course could come with a specialized charting widget. Room client attributes need to be considered in conjunction with these features: imagine if students were given the same permissions as instructors. A music class could easily become a cacophonous zoo, while the chaos level of a statistics class over time might start to resemble the trajectory of a jet taking off to the moon. In Syncosaurus, the room name is specified by passing it to the `launch` method of a `Syncosaurus` instance: @@ -12,11 +14,12 @@ In Syncosaurus, the room name is specified by passing it to the `launch` method import mutators from './mutators.js'; const synco = new Syncosaurus({ - mutators, userID: "my-user-id", server: "https://my-cool-app.workers.dev", auth: "E3B6CD6A-1EDC-49B8-B2CF-7372583145A6", + mutators, }); +//highlight-next-line synco.launch('my-room-name'); ``` diff --git a/docs/core-concepts/subscriptions.md b/docs/core-concepts/subscriptions.md index 39544a3..31c6f3f 100644 --- a/docs/core-concepts/subscriptions.md +++ b/docs/core-concepts/subscriptions.md @@ -6,9 +6,9 @@ sidebar_position: 4 A **subscription** allows clients to monitor if and when changes occur to the shared state of a room, regardless if the source of a change is local or from the authoritative server. -A **query** is a request for a specific type of subscription, and works hand-in-hand with subscriptions, allowing for customization of what state changes are being monitored. Queries are able to filter, aggregate and transform the shared state, or only portions of the shared state, to enable more granular application behavior and logic. These abilities are non-mutating and do not affect the shared application state, as it is only the server that can dictate final changes to shared state. +A **query** specifies *what* shared state changes a subcription monitors, and also *how*. Queries are able to filter, aggregate and transform the shared state, or only portions of the shared state, to enable more granular application behavior and logic. These abilities are non-mutating and do not affect the shared application state, as under the hood, they are utilizing [read transactions](transactions.md). -At the implementation level, a *subscription* is represented by the return value of `useSubscribe`, a custom React hook that uses the [useState](https://react.dev/reference/react/useState) React hook to monitor data from the local client state. What an update to this monitored data occurs, associated UI components re-renders with this refreshed data. At the implementation level, a *query* is a developer-defined function, whose return value dictates what is considered a subscription update. Whenever a query's return value changes, its subscription is activated, and UI components that are connected to that subscription are updated. +At the implementation level, a *subscription* is represented by the return value of `useSubscribe`, a custom React hook that uses the [useState](https://react.dev/reference/react/useState) React hook to monitor data from the local client state. When an update to this monitored data occurs, associated UI components re-render with this refreshed data. At the implementation level, a *query* is a developer-defined function, whose return value dictates what is considered a subscription update. Whenever a query's return value changes, its subscription is activated, and UI components that are connected to that subscription are updated. Here is a simple implementation of a subscription and its query: @@ -21,3 +21,5 @@ Here, we call the `useSubscribe` hook, and pass in three arguments: - The first argument is always a `Syncosaurus` instance, which has access to the local client state and the complete list of active subscriptions. - The second argument is our *query*. The *query* function must be defined with `tx` as its only parameter. This `tx` parameter is what allows a query and subscription to monitor the local client state for their specified changes. - The third argument is the initial starting value. If there are not yet changes to the local state that is relevant to the subscription, then the `useSubscribe` hook will return this initial starting value. + +The return value of `useSubscribe` is the part of the shared state we specified to monitor, in this case, the value at the key `count`. diff --git a/docs/core-concepts/transactions.md b/docs/core-concepts/transactions.md index c1b2923..67a4b6c 100644 --- a/docs/core-concepts/transactions.md +++ b/docs/core-concepts/transactions.md @@ -4,14 +4,30 @@ sidebar_position: 2 # Transactions -A **transaction** represents a single update, which can be either from a client to the server, or the server to a client. +A **transaction** represents a single [client](rooms.md) update. -In a Syncosaurus application, since the server is the authority, every transaction must be confirmed by the server before being broadcasted to other clients in a room. +In a Syncosaurus application, since the server is the authority, the server must confirm every transaction before being broadcast to other clients in a room. -A transaction, as an instance of the `transaction` class, consists of: +At the implementation level, a transaction consists of: - methods that allow mutators and queries to update and read from the local client state, key-value store - metadata on the transaction it represents, specifically *when* and *how* the application state should be updated -In Syncosaurus, transactions are categorized as either *read transactions* or *write transactions*. As their names imply, transactions are either observing or changing a specified part of the shared application state. +Transactions are categorized as either *read transactions* or *write transactions*. As their names imply, transactions are either observing or changing a specified part of the shared application state. -It is specifically through *write transactions* that [mutations](https://syncosaurus.github.io/docs/core-concepts/mutators) are applied to the shared state of a collaborative application. +## Read Transactions + +Read transactions are instances of the `ReadTransaction` class, and have access to the following methods: + - `get` - returns the value for the key from the local store based on a given key + - `has` - returns true if a given key exists in the local store + - `isEmpty` - returns true if the local store is empty + - `scan` - returns an object containing a subset of KV pairs from the local store where a developer-defined callback evaluates to true + +[Subscription queries](subscriptions.md) utilize read transactions to monitor for changes in the shared state of a collaborative applications. + +## Write Transactions + +Write transations are instances of the `WriteTransaction` class, and have access to the listed `ReadTransaction` instance methods above, in addition to the `set` and `delete` methods: + - `set` - updates the value of a given key in the local store + - `delete` - deletes a given key (and therefore value) from the local store + +[Mutations](mutators.md) are applied to the shared state of a collaborative application though write transactions. diff --git a/docs/getting-started/add-to-existing-project.md b/docs/getting-started/add-to-existing-project.md index d27d680..e9a5aff 100644 --- a/docs/getting-started/add-to-existing-project.md +++ b/docs/getting-started/add-to-existing-project.md @@ -13,8 +13,6 @@ npx syncosaurus setup That's it! Make sure to correctly configure your Syncosaurus application before deployment - see here for details. -Note that Syncosaurus currently only supports applications built with either React or a React-based framework. - ## Spin up a local development environment A local development environment makes it significantly easier to rapidly iterate, test, and debug your application in a consistent, controlled setting. Syncosaurus comes built-in with a local Syncosaurus server. @@ -40,10 +38,10 @@ Press 'x' to gracefully shut down the server Make sure to update your `server` value in your Syncosaurus constructor calls in your application code: ```js title="/src/components/App.jsx" -import mutators from './mutators.js'; +import mutators from '../mutators.js'; const synco = new Syncosaurus({ - // update this value to the local Syncosaurus server URL + // highlight-next-line server: "http://localhost:8787", userID: "my-user-id", auth: "4fJbGOWma=QEebX6H1X6AAe3/yok1R-fwKMqot5XOvxPU0YwI!sm8nQ!" @@ -53,14 +51,15 @@ const synco = new Syncosaurus({ ## Deploy your Syncosaurus project -When you are ready to deploy your Syncosaurus application, make sure the following requirements are first met: +Before you deploy your Syncosaurus application, make sure the following requirements are met: -1. Make sure that you are logged in to Cloudflare. - 1. You can check your login status with `syncosaurus whoami` - 2. If you are not logged in, run `syncosaurus login` and provide your Cloudflare credentials via OAuth or API token. -2. Navigate to your root directory of your project, which needs to have a `syncosaurus.json` configuration file. -3. Make sure your mutators are correctly defined in your `mutators.js` file, and your `mutators.js` file is located in the `src` sub-directory. -4. Make sure your authentication handler is correctly defined in your `authHandler.js` file, and your `authHandler.js` file is located in the `src` sub-directory. +- You are logged in to Cloudflare. + - You can check your login status with `syncosaurus whoami` + - If you are not logged in, run `syncosaurus login` and log in via OAuth or API token. +- You are in the root directory of your project, which must have `syncosaurus.json` configuration file. +- Your mutators are correctly defined in your `mutators.js` file, and your `mutators.js` file is located in the `src` sub-directory. +- Your `auth` value is defined correctly in the Syncosaurus constructor +- Your authentication handler is correctly defined in your `authHandler.js` file, and your `authHandler.js` file is located in the `src` sub-directory. Once the above requirements have been fulfilled, run the following command in your terminal: @@ -68,7 +67,7 @@ Once the above requirements have been fulfilled, run the following command in yo npx syncosaurus deploy ``` -If your application was configured correctly, the URL to your deployed application should be displayed in your terminal output, which will look akin to the output displayed below: +If your application was configured correctly, the URL to your deployed application should be displayed in your terminal output, which should look similar to the output displayed below: ```shell ❯ npx syncosaurus deploy @@ -77,8 +76,7 @@ If your application was configured correctly, the URL to your deployed applicati Evolving your Syncosaurus server... done! -✅ Success! Your Syncosaurus server is available at - https://my-cool-app.johnsmith.workers.dev +✅ Success! Your Syncosaurus server is available at https://dino-arcade.petrie.workers.dev ``` -To deploy your frontend, simply add this URL as an environment variable in your frontend application's directory. +To deploy your frontend, simply add the provided Syncosaurus server URL as an environment variable to your frontend deployment. diff --git a/docs/getting-started/start-a-new-project.md b/docs/getting-started/start-a-new-project.md index d2d12e0..debc02c 100644 --- a/docs/getting-started/start-a-new-project.md +++ b/docs/getting-started/start-a-new-project.md @@ -4,8 +4,6 @@ sidebar_position: 1 # Start a New Project -## Setup - To create a new Syncosaurus application, simply run the following command in your terminal: ```shell @@ -16,7 +14,7 @@ That's it! Follow the prompts to set up your new Syncosaurus project. ## Spin up a local development environment -A local development environment makes it significantly easier to rapidly iterate, test, and debug your application in a consistent, controlled setting. Syncosaurus comes built-in with both a local Syncosaurus server. If you are building a Syncosaurus project from scratch using `syncosaurus init`, Syncosaurus includes a local Vite UI server as well. +A local development environment makes it significantly easier to rapidly iterate, test, and debug your application in a consistent, controlled setting. Syncosaurus comes built-in with a local Syncosaurus server. If you are building a project from scratch using `syncosaurus init`, Syncosaurus includes a local Vite UI server as well. To start both the Syncosaurus server and the Vite UI server, run the following command in your terminal: @@ -30,10 +28,10 @@ If your file structure adheres to Syncosaurus rules, and your configuration sett - a localhost address for your local Vite UI server - The port used will be determined by Vite. Vite's default port is port 5173. If that port is being used, Vite will find and designate the next available port. -Your output will look something like the following: +Your output should something like the following: ```shell -my-projects/my-synco-app via ⬢ v21.7.1 +my-projects/dino-arcade via ⬢ v21.7.1 ❯ npx syncosaurus dev Checking for Syncosaurus installation...... found Initializing local dev environment...... done! @@ -48,10 +46,10 @@ Press 'x' to gracefully shut down both servers Make sure to update your `server` value in your Syncosaurus constructor calls in your application code: ```js title="/src/components/App.jsx" -import mutators from './mutators.js'; +import mutators from '../mutators.js'; const synco = new Syncosaurus({ - // update this value to the local Syncosaurus server URL + // highlight-next-line server: "http://localhost:8787", userID: "my-user-id" auth: "4fJbGOWma=QEebX6H1X6AAe3/yok1R-fwKMqot5XOvxPU0YwI!sm8nQ!" @@ -63,14 +61,15 @@ Now you're all set - freely iterate on your application, and see your code chang ## Deploy your Syncosaurus application -When you are ready to deploy your Syncosaurus application, make sure the following requirements are first met: +Before you deploy your Syncosaurus application, make sure the following requirements are met: -1. Make sure that you are logged in to Cloudflare. - 1. You can check your login status with `syncosaurus whoami` - 2. If you are not logged in, run `syncosaurus login` and provide your Cloudflare credentials via OAuth or API token. -2. Navigate to your root directory of your project, which needs to have a `syncosaurus.json` configuration file. -3. Make sure your mutators are correctly defined in your `mutators.js` file, and your `mutators.js` file is located in the `src` sub-directory. -4. Make sure your authentication handler is correctly defined in your `authHandler.js` file, and your `authHandler.js` file is located in the `src` sub-directory. +- You are logged in to Cloudflare. + - You can check your login status with `syncosaurus whoami` + - If you are not logged in, run `syncosaurus login` and log in via OAuth or API token. +- You are in the root directory of your project, which must have `syncosaurus.json` configuration file. +- Your mutators are correctly defined in your `mutators.js` file, and your `mutators.js` file is located in the `src` sub-directory. +- Your `auth` value is defined correctly in the Syncosaurus constructor +- Your authentication handler is correctly defined in your `authHandler.js` file, and your `authHandler.js` file is located in the `src` sub-directory. Once the above requirements have been fulfilled, run the following command in your terminal: @@ -78,7 +77,7 @@ Once the above requirements have been fulfilled, run the following command in yo npx syncosaurus deploy ``` -If your application was configured correctly, the URL to your deployed application should be displayed in your terminal output, which will look akin to the output displayed below: +If your application was configured correctly, the URL to your deployed application should be displayed in your terminal output, which should look similar to the output displayed below: ```shell ❯ npx syncosaurus deploy @@ -87,8 +86,7 @@ If your application was configured correctly, the URL to your deployed applicati Evolving your Syncosaurus server... done! -✅ Success! Your Syncosaurus server is available at - https://my-cool-app.johnsmith.workers.dev +✅ Success! Your Syncosaurus server is available at https://dino-arcade.ducky.workers.dev ``` -To deploy your frontend, simply add this URL as an environment variable for your frontend deployment. +To deploy your frontend, simply add the provided Syncosaurus server URL as an environment variable to your frontend deployment. diff --git a/docs/guides/analytics.md b/docs/guides/analytics.md index c0da0d7..5d4ba54 100644 --- a/docs/guides/analytics.md +++ b/docs/guides/analytics.md @@ -8,16 +8,28 @@ Syncosaurus includes an application analytics tool to easily view and analyze ag ## Setup -- Clone this repository to your local environment: git clone https://github.com/syncosaurus/syncosaurus-dashboard.git -- Create an `.env` file with the following environment variables and values in the root directory: +1. Clone the repository to your local environment, and install the required dependencies: + ```shell + git clone https://github.com/syncosaurus/syncosaurus-dashboard.git + ``` + +2. Create an `.env` file with the following environment variables and values in the root directory: - `CLOUDFLARE_ACCOUNT_ID`: This is the account ID associated with your Cloudflare account. For instructions on finding your account ID, click [here](https://developers.cloudflare.com/fundamentals/setup/find-account-and-zone-ids/). - `BEARER_AUTH`: This is an Cloudflare Analytics API token associated with your account. This is used to access the GraphQL Analytics API. For instructions on creating an API token, click [here](https://developers.cloudflare.com/analytics/graphql-api/getting-started/authentication/api-token-auth/). - `X_AUTH_EMAIL`: This is the e-mail address associated with your Cloudflare account. - `X_AUTH_KEY`: This is your Cloudflare global API key. This is used to access the Cloudflare API. For instructions on finding your global API key, click [here](https://developers.cloudflare.com/fundamentals/api/get-started/keys/). - `PORT`: This is the local port that you want the dashboard app to use. If this value does not exist, the application defaults to port 3001. -- Install dependencies: `npm install` -- Run the dashboard application: `npm start` -- An URL to the dashboard application will be displayed (ex: http://localhost:3001). Click the URL to launch the dashboard application. +3. Install dependencies: + ```shell + npm install + ``` + +4. Run the dashboard application: + ```shell + npm start + ``` + +5. An URL to the dashboard application will be displayed (ex: http://localhost:3001). Click the URL to launch the dashboard application. ## Metrics Info diff --git a/docs/guides/authentication.md b/docs/guides/authentication.md index e79e128..bd8ca29 100644 --- a/docs/guides/authentication.md +++ b/docs/guides/authentication.md @@ -13,13 +13,13 @@ The Syncosaurus framework supports token-based authentication. JSON web tokens a To use a token, you can directly pass a *token string* to the `Syncosaurus` constructor as the `auth` key's value: ```js title="/src/components/App.jsx" -import mutators from './mutators.js'; +import mutators from '../mutators.js'; const synco = new Syncosaurus({ mutators, - userID: "my--user-id", + userID: "my-user-id", server: "https://my-cool-app.workers.dev", - // Pass your authentication token here + // highlight-next-line auth: "E3B6CD6A-1EDC-49B8-B2CF-7372583145A6", }); ``` @@ -27,14 +27,14 @@ const synco = new Syncosaurus({ You can also pass an *asynchronous function* that returns a token string to the `Syncosaurus` constructor as the `auth` key's value: ```js title="/src/components/App.jsx" -import mutators from './mutators.js'; -import getToken from './auth-client.js'; +import mutators from '../mutators.js'; +import getToken from '../auth-client.js'; const synco = new Syncosaurus({ mutators, userID: "my--user-id", server: "https://my-cool-app.workers.dev", - // Pass your async fn that returns an auth token here + // highlight-next-line auth: async () => return await getToken(), }); ``` @@ -44,12 +44,10 @@ const synco = new Syncosaurus({ Next, an `authHandler` function needs to be defined: ```js title="/src/authHandler.js" -const authServerUrl = `https://www.myAuthServer.com`; - export default async function authHandler(token) { try { - const response = await fetch(`${authServerUrl}/verify?token=${token}`); - const { payload } = response.json(); + const response = await fetch(`${env.authServerUrl}/verify?token=${token}`); + const { payload } = await response.json(); const { userID } = payload; return userID; } catch (error) { @@ -60,12 +58,12 @@ export default async function authHandler(token) { ### Configuration -Note that in order for your Syncosaurus server to correctly read, access, and verify your authentication token(s), the authentication handler function `authHandler` must adhere to the following requirements: +Note that for your Syncosaurus server to correctly read, access, and verify your authentication token(s), the authentication handler function `authHandler` must adhere to the following requirements: - The function must be named `authHandler` - The function must be placed in the `src` subdirectory of your Syncosaurus project. Do not place `authHandler.js` in a subdirectory of the `src` directory. - `authHandler.js` must be a module that exports the `authHandler` function as its default export. -Both the `auth` token and the `authHandler` function need to be correctly defined and appropriately handle errors in order for Syncosaurus to correctly implement authentication in your application. +Both the `auth` token and the `authHandler` function need to be correctly defined and appropriately handle errors for Syncosaurus to correctly implement authentication in your application. - If the above requirements are not met, then authentication will not be configured, and will be skipped. - However, the Syncosaurus server will reject a request if: - `auth` is either a string or function and `authHandler` is a function, and the `authHandler` function throws any type of error. diff --git a/docs/guides/configuration.md b/docs/guides/configuration.md index ec04aa2..dd8ad76 100644 --- a/docs/guides/configuration.md +++ b/docs/guides/configuration.md @@ -21,7 +21,7 @@ The default value of `msgFrequency` is `16` (ms), which equates to approximately ### `useStorage` -This value determines whether your application persists data to the Syncosaurus server using [Cloudflare's Transactional Storage API](https://developers.cloudflare.com/durable-objects/api/transactional-storage-api/) +This value determines whether your application persists data to the Syncosaurus server using [Cloudflare's Transactional Storage API](https://developers.cloudflare.com/durable-objects/api/transactional-storage-api/). The default value of `useStorage` is `false`. diff --git a/docs/index.md b/docs/index.md index bd76b7f..0d43651 100644 --- a/docs/index.md +++ b/docs/index.md @@ -12,7 +12,9 @@ Built with Cloudflare's [Durable Objects](https://developers.cloudflare.com/dura ## Features -- An synchronization engine based on server reconciliation +- A synchronization engine based on [client-side prediction and server reconciliation](https://gabrielgambetta.com/client-side-prediction-server-reconciliation.html) - The ability to automatically persist state on a per-room basis - A convenient CLI tool to seamlessly create, configure, manage, and deploy your collaborative application -- An analytics dashboard to monitor your collaborative application's usage and error metrics \ No newline at end of file +- An [analytics dashboard](guides/analytics.md) to monitor usage and error metrics +- [Authentication](guides/authentication.md) support to secure your [rooms](core-concepts/rooms.md) +- [Presence](core-concepts/presence.md) support to broadcast ephemeral data, including live cursors and live status updates \ No newline at end of file From cd08ca47750a7de98096adcd005c1efb9a5b3bd2 Mon Sep 17 00:00:00 2001 From: jgoteam Date: Wed, 24 Apr 2024 12:28:18 -0700 Subject: [PATCH 02/12] docs: more docs polish - added 'Requirements' page and 'Syncosaurus CLI' page - edits and polish to existing pages, mainly core-concept pages - resize latency slider - removed unnecessary imports in HomePageFeatures component Co-authored-by: Alex Sklar Co-authored-by: Erik Margetis --- .../add-to-existing-project.md | 8 +- docs/getting-started/requirements.md | 19 ++++ docs/getting-started/start-a-new-project.md | 10 +- docs/getting-started/walkthrough.md | 5 - docs/guides/analytics.md | 2 +- docs/guides/configuration.md | 2 +- docs/guides/syncosaurus-cli.md | 93 +++++++++++++++++++ src/components/HomepageFeatures/index.js | 6 +- .../LatencySlider/VerticalSlider.js | 1 + .../LatencySlider/VerticalSliderContainer.js | 3 +- 10 files changed, 124 insertions(+), 25 deletions(-) create mode 100644 docs/getting-started/requirements.md delete mode 100644 docs/getting-started/walkthrough.md create mode 100644 docs/guides/syncosaurus-cli.md diff --git a/docs/getting-started/add-to-existing-project.md b/docs/getting-started/add-to-existing-project.md index e9a5aff..cc4793f 100644 --- a/docs/getting-started/add-to-existing-project.md +++ b/docs/getting-started/add-to-existing-project.md @@ -71,12 +71,10 @@ If your application was configured correctly, the URL to your deployed applicati ```shell ❯ npx syncosaurus deploy - 🦖 syncosaurus 0.7.1 +Checking for Syncosaurus installation...... found +Deploying your Syncosaurus worker...... done! -------------------------------------------------- - -Evolving your Syncosaurus server... done! - -✅ Success! Your Syncosaurus server is available at https://dino-arcade.petrie.workers.dev +🦖 Your deployed Syncosaurus worker is ready at https://dino-arcade.petrie.workers.dev ``` To deploy your frontend, simply add the provided Syncosaurus server URL as an environment variable to your frontend deployment. diff --git a/docs/getting-started/requirements.md b/docs/getting-started/requirements.md new file mode 100644 index 0000000..5399d20 --- /dev/null +++ b/docs/getting-started/requirements.md @@ -0,0 +1,19 @@ +--- +sidebar_position: 1 +--- + +# Requirements + +Before using Syncosaurus, ensure the following requirements are met: + +- [Node](https://nodejs.org/en) v18+ +- [npm](https://www.npmjs.com/) +- A frontend that utilizes [React](https://react.dev/) v16.8+ +- Paid Cloudflare account with access to [Durable Objects](https://developers.cloudflare.com/durable-objects/) +- Access to the [Syncosaurus CLI](https://github.com/syncosaurus/syncosaurus-cli) + - This requirement can be fulfilled in two ways: + - *Recommended*: Use the [`npx`](https://www.npmjs.com/package/npx) feature to directly run Syncosaurus CLI commands without installing the Syncosaurus CLI application + - Alternatively, you may also install the Syncosaurus CLI locally: + ```shell + npm install -g syncosaurus-cli + ``` diff --git a/docs/getting-started/start-a-new-project.md b/docs/getting-started/start-a-new-project.md index debc02c..19fef64 100644 --- a/docs/getting-started/start-a-new-project.md +++ b/docs/getting-started/start-a-new-project.md @@ -24,7 +24,7 @@ npx syncosaurus dev If your file structure adheres to Syncosaurus rules, and your configuration settings are correct, two localhost addresses will be displayed in your terminal output: - a localhost address for your local Syncosaurus server - - The port used will be the port you designated in the `syncosaurus.json` file. If one is not specified there, the local Syncosaurus server will default to port 3001. + - The port used will be the port you designated in the `syncosaurus.json` file. If one is not specified there, the local Syncosaurus server will default to port 8787. - a localhost address for your local Vite UI server - The port used will be determined by Vite. Vite's default port is port 5173. If that port is being used, Vite will find and designate the next available port. @@ -81,12 +81,10 @@ If your application was configured correctly, the URL to your deployed applicati ```shell ❯ npx syncosaurus deploy - 🦖 syncosaurus 0.7.1 +Checking for Syncosaurus installation...... found +Deploying your Syncosaurus worker...... done! -------------------------------------------------- - -Evolving your Syncosaurus server... done! - -✅ Success! Your Syncosaurus server is available at https://dino-arcade.ducky.workers.dev +🦖 Your deployed Syncosaurus worker is ready at https://dino-arcade.ducky.workers.dev ``` To deploy your frontend, simply add the provided Syncosaurus server URL as an environment variable to your frontend deployment. diff --git a/docs/getting-started/walkthrough.md b/docs/getting-started/walkthrough.md deleted file mode 100644 index 469a669..0000000 --- a/docs/getting-started/walkthrough.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -sidebar_position: 3 ---- - -# Walkthrough \ No newline at end of file diff --git a/docs/guides/analytics.md b/docs/guides/analytics.md index 5d4ba54..8a5ca91 100644 --- a/docs/guides/analytics.md +++ b/docs/guides/analytics.md @@ -8,7 +8,7 @@ Syncosaurus includes an application analytics tool to easily view and analyze ag ## Setup -1. Clone the repository to your local environment, and install the required dependencies: +1. Clone the following repository to your local environment: ```shell git clone https://github.com/syncosaurus/syncosaurus-dashboard.git ``` diff --git a/docs/guides/configuration.md b/docs/guides/configuration.md index dd8ad76..19a3a94 100644 --- a/docs/guides/configuration.md +++ b/docs/guides/configuration.md @@ -16,7 +16,7 @@ This is the name of your Syncosaurus project. This value will be used when deplo ### `msgFrequency` -This is the amount of time (in milliseconds) that subsequent message broadcast of app updates should be delayed. +This is the amount of time (in milliseconds) that subsequent message broadcasts of app updates should be delayed. The default value of `msgFrequency` is `16` (ms), which equates to approximately 62.5 broadcasted updates per second. ### `useStorage` diff --git a/docs/guides/syncosaurus-cli.md b/docs/guides/syncosaurus-cli.md new file mode 100644 index 0000000..40d37e0 --- /dev/null +++ b/docs/guides/syncosaurus-cli.md @@ -0,0 +1,93 @@ +--- +sidebar_position: 4 +--- + +# Syncosaurus CLI + +The Syncosaurus CLI application is used to conveniently create, configure, manage, and deploy Syncosaurus applications. Built in Typescript with the [oclif](https://oclif.io/) framework. + +## Installation + +- It is recommended to utilize the Syncosaurus CLI with `npx` commands, without having to install the application locally. +- If you still wish to install the Syncosaurus CLI locally, run `npm install -g syncosaurus-cli`. + +## Setup and Development Commands + +If you are electing to run the Syncosaurus CLI locally, simply remove the `npx` at the beginning of the commands below. + +### `syncosaurus init` + +- Create a new React application, pre-configured with a Syncosaurus multiplayer backend. Note that this command will create a `syncosaurus.json` configuration file in your root directory. + + ```bash + npx syncosaurus init + ``` + +### `syncosaurus setup` + +- Add Syncosaurus to an existing React-based application. Note that this command will also create a `syncosaurus.json` configuration file in your root directory. + + ```bash + npx syncosaurus setup + ``` + +### `syncosaurus dev` + +- Start a local Syncosaurus development environment. Run without any flags to start up both a local Syncosaurus server and a local Vite UI server. Run with the `-b`/`-backendOnly` flag to start up only a local Syncosaurus server. + - The local Syncosaurus server will use the designated port, as specified by a `PORT` value in your local `.env` file. If no such value exists, it will default to port 8787. + + ```bash + npx syncosaurus dev [-b] + ``` +

+## Deployment Commands + +### `syncosaurus deploy` + +- Deploy your Syncosaurus application. You must be logged in to use this command. + + ```bash + npx syncosaurus deploy + ``` + +### `syncosaurus destroy` + +- Delete your most recent deployment, only if that deployment matches the current project. You must be logged in to use this command. + + ```bash + npx syncosaurus destroy + ``` + +### `syncosaurus tail` + +- Setup a tail log stream for a deployed Syncosaurus worker. + + ```bash + npx syncosaurus tail + ``` + +## Authentication Commands + +### `syncosaurus login` + +- Login to Synocosaurus through OAuth or API token. + + ```bash + npx syncosaurus login + ``` + +### `syncosaurus logout` + +- Logout of Syncosaurus. + + ```bash + npx syncosaurus logout + ``` + +### `syncosaurus whoami` + +- Check your current Syncosaurus login status. + + ```bash + npx syncosaurus whoami + ``` \ No newline at end of file diff --git a/src/components/HomepageFeatures/index.js b/src/components/HomepageFeatures/index.js index d1e8b08..f143d98 100644 --- a/src/components/HomepageFeatures/index.js +++ b/src/components/HomepageFeatures/index.js @@ -1,7 +1,3 @@ -import clsx from 'clsx' -import Heading from '@theme/Heading' -import styles from './styles.module.css' - import FadeInSection from './FadeInSection' export default function HomepageFeatures() { @@ -22,7 +18,7 @@ export default function HomepageFeatures() {
diff --git a/src/components/LatencySlider/VerticalSlider.js b/src/components/LatencySlider/VerticalSlider.js index fe898e0..1c03268 100644 --- a/src/components/LatencySlider/VerticalSlider.js +++ b/src/components/LatencySlider/VerticalSlider.js @@ -51,6 +51,7 @@ const Slider = styled(BaseSlider)( display: inline-block; position: relative; margin-top: 0.75rem; + margin-right: 3.25rem; cursor: ${delay === 0 ? "pointer" : null}; touch-action: none; -webkit-tap-highlight-color: transparent; diff --git a/src/components/LatencySlider/VerticalSliderContainer.js b/src/components/LatencySlider/VerticalSliderContainer.js index ce8fe0a..25ee39c 100644 --- a/src/components/LatencySlider/VerticalSliderContainer.js +++ b/src/components/LatencySlider/VerticalSliderContainer.js @@ -5,10 +5,9 @@ const VerticalSliderContainer = styled(Box)(({ theme }) => ({ justifyContent: 'center', alignItems: 'center', padding: '3rem', - margin: '5rem', marginBottom: '0.75rem', marginTop: '0.75rem', - gap: theme.spacing(50), // Adjust the gap between sliders + gap: theme.spacing(50, 'auto'), // Adjust the gap between sliders })); export default VerticalSliderContainer; \ No newline at end of file From 751a4e0c59035afb855c3852409d7594c0930c32 Mon Sep 17 00:00:00 2001 From: jgoteam Date: Wed, 24 Apr 2024 14:12:40 -0700 Subject: [PATCH 03/12] style: minor homepage benefit bar cosmetic update Co-authored-by: Alex Sklar Co-authored-by: Erik Margetis --- src/components/Benefits/index.js | 71 ++++++++++++++------------------ src/css/custom.css | 7 ++++ src/pages/index.js | 2 +- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/components/Benefits/index.js b/src/components/Benefits/index.js index 0ed1e2a..eed6ddd 100644 --- a/src/components/Benefits/index.js +++ b/src/components/Benefits/index.js @@ -1,48 +1,41 @@ -import clsx from 'clsx' -import Heading from '@theme/Heading' -import styles from './styles.module.css' import FadeInSection from './FadeInSection' export default function HomepageBenefits() { return ( -
-
-
-
-

- Ready to Scale -

- -

- Scalable infrastructure
built with Cloudflare -

- - -
-

- Quick to Integrate -

- -

- React SDK to quickly add
- new features to your app -

- - -
-

- Easy to Configure -

- -

- Config file to customize
- default syncing behavior -

- +
+
+
+

+ Ready to Scale +

+ +

+ Scalable infrastructure
built with Cloudflare +

+
+
+

+ Quick to Integrate +

+ +

+ React SDK to quickly add
+ new features to your app +

+
+
+

+ Easy to Configure +

+ +

+ Config file to customize
+ default syncing behavior +

- - +
+
) } diff --git a/src/css/custom.css b/src/css/custom.css index 0389835..1885ad6 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -134,6 +134,13 @@ align-self: center; } +.benefits-bar { + align-items: center; + align-self: center; + width: 99.5%; + +} + .col--2 { --ifm-col-width: calc(20%); } diff --git a/src/pages/index.js b/src/pages/index.js index eb5916d..8884a46 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -21,7 +21,7 @@ export default function Home() {

{siteConfig.title}

From a7e26aa9bff85456a41629eefd92dcdf1867b46a Mon Sep 17 00:00:00 2001 From: jgoteam Date: Wed, 24 Apr 2024 14:27:56 -0700 Subject: [PATCH 04/12] chore: removed extraneous cloudflare icon and react icon images Co-authored-by: Alex Sklar Co-authored-by: Erik Margetis --- src/components/Benefits/Cloudflare_Logo.svg | 26 -------------------- src/components/Benefits/react_logo.png | Bin 18178 -> 0 bytes tailwind.config.js | 2 +- 3 files changed, 1 insertion(+), 27 deletions(-) delete mode 100644 src/components/Benefits/Cloudflare_Logo.svg delete mode 100644 src/components/Benefits/react_logo.png diff --git a/src/components/Benefits/Cloudflare_Logo.svg b/src/components/Benefits/Cloudflare_Logo.svg deleted file mode 100644 index a1406cf..0000000 --- a/src/components/Benefits/Cloudflare_Logo.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - Cloudflare logo - - - - - diff --git a/src/components/Benefits/react_logo.png b/src/components/Benefits/react_logo.png deleted file mode 100644 index 4008d38000a06ce4c1de465025de29e76537b554..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18178 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 Z`G5AC2(*RrOoRXc002ovPDHLkV1k(Cx%&VB diff --git a/tailwind.config.js b/tailwind.config.js index aeedebd..ac14698 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -13,7 +13,7 @@ module.exports = { extend: { fontFamily: { sans: ['"Inter"', ...fontFamily.sans], - jakarta: ['Plus Jakarta Sans', ...fontFamily.sans], + jakarta: ['"Plus Jakarta Sans"', ...fontFamily.sans], mono: ['"Fira Code"', ...fontFamily.mono], }, borderRadius: { From 18030b7a382fc2a5eb741f1d8b0c55f2b901b1d3 Mon Sep 17 00:00:00 2001 From: Alex Sklar Date: Wed, 24 Apr 2024 15:33:39 -0700 Subject: [PATCH 05/12] feat(diag): add color to diagrams Co-authored-by: Erik Margetis Co-authored-by: Joseph Liang --- static/img/diagrams/diag-absolute-update.svg | 4 +-- static/img/diagrams/diag-centralized.svg | 2 +- static/img/diagrams/diag-conflict-edits.svg | 4 +-- static/img/diagrams/diag-long-polling.svg | 4 +-- .../diagrams/diag-new-client-connection.svg | 4 +-- .../img/diagrams/diag-no-conflict-edits.svg | 4 +-- static/img/diagrams/diag-p2p.svg | 2 +- static/img/diagrams/diag-relative-update.svg | 26 +++++++++---------- .../img/diagrams/diag-websocket-handshake.svg | 4 +-- .../img/diagrams/diag-whiteboard-conflict.svg | 4 +-- .../diag-whiteboard-demo-dual-latency.svg | 14 +++++----- .../diagrams/diag-whiteboard-demo-dual.svg | 14 +++++----- tailwind.config.js | 2 +- 13 files changed, 44 insertions(+), 44 deletions(-) diff --git a/static/img/diagrams/diag-absolute-update.svg b/static/img/diagrams/diag-absolute-update.svg index db584eb..5d89c94 100644 --- a/static/img/diagrams/diag-absolute-update.svg +++ b/static/img/diagrams/diag-absolute-update.svg @@ -1,6 +1,6 @@ - + diff --git a/static/img/diagrams/diag-centralized.svg b/static/img/diagrams/diag-centralized.svg index 167886d..836b532 100644 --- a/static/img/diagrams/diag-centralized.svg +++ b/static/img/diagrams/diag-centralized.svg @@ -1 +1 @@ - + diff --git a/static/img/diagrams/diag-conflict-edits.svg b/static/img/diagrams/diag-conflict-edits.svg index e4a2945..38cf92e 100644 --- a/static/img/diagrams/diag-conflict-edits.svg +++ b/static/img/diagrams/diag-conflict-edits.svg @@ -1,6 +1,6 @@ - + diff --git a/static/img/diagrams/diag-long-polling.svg b/static/img/diagrams/diag-long-polling.svg index f912707..9bf3eb8 100644 --- a/static/img/diagrams/diag-long-polling.svg +++ b/static/img/diagrams/diag-long-polling.svg @@ -1,6 +1,6 @@ - + diff --git a/static/img/diagrams/diag-new-client-connection.svg b/static/img/diagrams/diag-new-client-connection.svg index 05fb580..a960d36 100644 --- a/static/img/diagrams/diag-new-client-connection.svg +++ b/static/img/diagrams/diag-new-client-connection.svg @@ -1,6 +1,6 @@ - + diff --git a/static/img/diagrams/diag-no-conflict-edits.svg b/static/img/diagrams/diag-no-conflict-edits.svg index c2ea07b..330aefa 100644 --- a/static/img/diagrams/diag-no-conflict-edits.svg +++ b/static/img/diagrams/diag-no-conflict-edits.svg @@ -1,6 +1,6 @@ - + diff --git a/static/img/diagrams/diag-p2p.svg b/static/img/diagrams/diag-p2p.svg index 4c9b733..fa9b57b 100644 --- a/static/img/diagrams/diag-p2p.svg +++ b/static/img/diagrams/diag-p2p.svg @@ -1 +1 @@ - + diff --git a/static/img/diagrams/diag-relative-update.svg b/static/img/diagrams/diag-relative-update.svg index d5d5a62..523dafc 100644 --- a/static/img/diagrams/diag-relative-update.svg +++ b/static/img/diagrams/diag-relative-update.svg @@ -1,30 +1,30 @@ - +<svg id="ep4eHtVS5nx1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 600 200" shape-rendering="geometricPrecision" text-rendering="geometricPrecision"><defs><filter id="ep4eHtVS5nx3-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ep4eHtVS5nx3-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="8,8"/><feOffset id="ep4eHtVS5nx3-filter-drop-shadow-0-offset" dx="7" dy="7" result="tmp"/><feFlood id="ep4eHtVS5nx3-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.4)"/><feComposite id="ep4eHtVS5nx3-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ep4eHtVS5nx3-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ep4eHtVS5nx3-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ep4eHtVS5nx3-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><linearGradient id="ep4eHtVS5nx3-fill" x1="0.5" y1="0" x2="0.5" y2="1" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="ep4eHtVS5nx3-fill-0" offset="0%" stop-color="#7ed348"/><stop id="ep4eHtVS5nx3-fill-1" offset="100%" stop-color="#1d3370"/></linearGradient><filter id="ep4eHtVS5nx23-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ep4eHtVS5nx23-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="8,8"/><feOffset id="ep4eHtVS5nx23-filter-drop-shadow-0-offset" dx="5" dy="5" result="tmp"/><feFlood id="ep4eHtVS5nx23-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.3)"/><feComposite id="ep4eHtVS5nx23-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ep4eHtVS5nx23-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ep4eHtVS5nx23-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ep4eHtVS5nx23-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><filter id="ep4eHtVS5nx24-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ep4eHtVS5nx24-filter-inner-shadow-0-blur" in="SourceAlpha" stdDeviation="2,2"/><feOffset id="ep4eHtVS5nx24-filter-inner-shadow-0-offset" dx="2" dy="2" result="tmp"/><feComposite id="ep4eHtVS5nx24-filter-inner-shadow-0-composite" operator="arithmetic" k2="-1" k3="1" in2="SourceGraphic"/><feColorMatrix id="ep4eHtVS5nx24-filter-inner-shadow-0-color-matrix" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.24 0"/><feMerge id="ep4eHtVS5nx24-filter-inner-shadow-0-merge" result="result"><feMergeNode id="ep4eHtVS5nx24-filter-inner-shadow-0-merge-node-1" in="SourceGraphic"/><feMergeNode id="ep4eHtVS5nx24-filter-inner-shadow-0-merge-node-2"/></feMerge><feGaussianBlur id="ep4eHtVS5nx24-filter-drop-shadow-0-blur" in="result" stdDeviation="1,1"/><feOffset id="ep4eHtVS5nx24-filter-drop-shadow-0-offset" dx="0" dy="0" result="tmp"/><feFlood id="ep4eHtVS5nx24-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.3)"/><feComposite id="ep4eHtVS5nx24-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ep4eHtVS5nx24-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ep4eHtVS5nx24-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ep4eHtVS5nx24-filter-drop-shadow-0-merge-node-2" in="result"/></feMerge></filter><linearGradient id="ep4eHtVS5nx24-fill" x1="0" y1="0" x2="0.98913" y2="1" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="ep4eHtVS5nx24-fill-0" offset="0%" stop-color="#fff6df"/><stop id="ep4eHtVS5nx24-fill-1" offset="100%" stop-color="#ffe194"/></linearGradient><linearGradient id="ep4eHtVS5nx25-fill" x1="0" y1="0" x2="0.98913" y2="1" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="ep4eHtVS5nx25-fill-0" offset="17.8259%" stop-color="rgba(255,255,255,0)"/><stop id="ep4eHtVS5nx25-fill-1" offset="20.901%" stop-color="#fff"/><stop id="ep4eHtVS5nx25-fill-2" offset="49.0384%" stop-color="#fff"/><stop id="ep4eHtVS5nx25-fill-3" offset="52.4724%" stop-color="rgba(255,255,255,0)"/></linearGradient><filter id="ep4eHtVS5nx27-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ep4eHtVS5nx27-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="8,8"/><feOffset id="ep4eHtVS5nx27-filter-drop-shadow-0-offset" dx="5" dy="5" result="tmp"/><feFlood id="ep4eHtVS5nx27-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.3)"/><feComposite id="ep4eHtVS5nx27-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ep4eHtVS5nx27-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ep4eHtVS5nx27-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ep4eHtVS5nx27-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><filter id="ep4eHtVS5nx28-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ep4eHtVS5nx28-filter-inner-shadow-0-blur" in="SourceAlpha" stdDeviation="2,2"/><feOffset id="ep4eHtVS5nx28-filter-inner-shadow-0-offset" dx="2" dy="2" result="tmp"/><feComposite id="ep4eHtVS5nx28-filter-inner-shadow-0-composite" operator="arithmetic" k2="-1" k3="1" in2="SourceGraphic"/><feColorMatrix id="ep4eHtVS5nx28-filter-inner-shadow-0-color-matrix" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/><feMerge id="ep4eHtVS5nx28-filter-inner-shadow-0-merge" result="result"><feMergeNode id="ep4eHtVS5nx28-filter-inner-shadow-0-merge-node-1" in="SourceGraphic"/><feMergeNode id="ep4eHtVS5nx28-filter-inner-shadow-0-merge-node-2"/></feMerge><feGaussianBlur id="ep4eHtVS5nx28-filter-drop-shadow-0-blur" in="result" stdDeviation="1,1"/><feOffset id="ep4eHtVS5nx28-filter-drop-shadow-0-offset" dx="0" dy="0" result="tmp"/><feFlood id="ep4eHtVS5nx28-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.4)"/><feComposite id="ep4eHtVS5nx28-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ep4eHtVS5nx28-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ep4eHtVS5nx28-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ep4eHtVS5nx28-filter-drop-shadow-0-merge-node-2" in="result"/></feMerge></filter><linearGradient id="ep4eHtVS5nx28-fill" x1="0" y1="0" x2="0.98913" y2="1" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="ep4eHtVS5nx28-fill-0" offset="0%" stop-color="#e8f9fd"/><stop id="ep4eHtVS5nx28-fill-1" offset="100%" stop-color="#c3ebf4"/></linearGradient><linearGradient id="ep4eHtVS5nx29-fill" x1="0" y1="0" x2="0.98913" y2="1" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="ep4eHtVS5nx29-fill-0" offset="17.8259%" stop-color="rgba(255,255,255,0)"/><stop id="ep4eHtVS5nx29-fill-1" offset="20.901%" stop-color="#fff"/><stop id="ep4eHtVS5nx29-fill-2" offset="49.0384%" stop-color="#fff"/><stop id="ep4eHtVS5nx29-fill-3" offset="52.4724%" stop-color="rgba(255,255,255,0)"/></linearGradient></defs><g transform="matrix(.1 0 0 0.1 239.872756 73.151915)"><path d="M1175.8,370.92v-189.1c1.2188-3.6562,0-7.2656-1.2188-10.922l-60.609-132.14c-2.4375-6.0469-9.7031-10.922-16.969-10.922l-991.5.046874c-7.2656,0-13.312,3.6562-16.969,10.922l-60.609,132.14c-1.2188,3.6562-2.4375,7.2656-1.2188,10.922v190.31c0,26.672,25.453,48.469,55.734,48.469l2.4375-.046876-56.953,123.66c-1.2188,3.6562-2.4375,7.2656-1.2188,10.922v190.31c0,26.672,25.453,48.469,55.734,48.469h3.6562l-58.172,124.82c-1.2188,3.6562-2.4375,7.2656-1.2188,10.922v190.31c0,26.672,24.234,48.469,55.734,48.469h1036.4c30.281,0,54.562-20.625,56.953-49.688l.046874-186.71v-2.4375c1.2188-3.6562,0-7.2656-1.2188-10.922l-56.953-124.82h1.2188c30.281,0,54.562-20.625,56.953-49.688v-189.1c1.2188-3.6562,0-7.2656-1.2188-10.922l-56.953-123.66h1.2188c30.281.046876,54.516-20.578,56.953-49.641L1175.8,370.92ZM117.6,64.26h968.48l32.719,71.531-1033.9-.046875L117.6,64.26ZM63.084,372.13v-187.87c0-6.0469,8.4844-12.141,19.406-12.141h1037.6c10.922,0,19.406,6.0469,19.406,12.141v185.44c0,8.4844-9.7031,14.531-20.625,14.531h-1036.4c-10.875,0-19.359-6.0469-19.359-12.094l-.028-.007Zm1055.7,759.98h-1036.4c-10.922,0-19.406-6.0469-19.406-12.141l.046875-187.87c0-6.0469,8.4844-12.141,19.406-12.141h1037.6c10.922,0,19.406,6.0469,19.406,12.141v185.44c-.046875,8.5312-9.75,14.578-20.672,14.578l.019125-.007Zm-38.766-330.89l37.594,82.406h-1032.7l37.594-82.406c1.2188-2.4375,1.2188-4.8281,1.2188-7.2656h56.953v32.719c0,15.75,13.312,27.891,27.891,27.891h787.87c15.75,0,27.891-12.141,27.891-27.891v-32.719l54.516-.046875c0,2.4375,0,4.875,1.2188,7.3125l-.0466-.000025Zm38.766-43.641h-1036.4c-10.922,0-19.406-6.0469-19.406-12.141l.046875-187.87c0-6.0469,8.4844-12.141,19.406-12.141h1037.6c10.922,0,19.406,6.0469,19.406,12.141v185.44c-.046875,8.4844-9.75,14.578-20.672,14.578l.019125-.007Zm-38.766-330.94l37.594,82.406-1032.7.046875l37.594-82.406c1.2188-2.4375,1.2188-3.6562,1.2188-6.0469h56.953v37.594c0,15.75,12.141,27.891,27.891,27.891h787.87c15.75,0,27.891-12.141,27.891-27.891v-37.594l54.516-.046875c0,2.4375,1.2188,4.8281,1.2188,6.0469h-.0466Z" filter="url(#ep4eHtVS5nx3-filter)" fill="url(#ep4eHtVS5nx3-fill)"/><path d="M1001.2,991.5c-19.406,0-35.156,15.75-35.156,35.156s15.75,35.156,35.156,35.156s35.156-15.75,35.156-35.156-15.75-35.156-35.156-35.156Z" fill="#29476b"/><path d="M866.68,991.5c-19.406,0-35.156,15.75-35.156,35.156s15.75,35.156,35.156,35.156s35.156-15.75,35.156-35.156-15.75-35.156-35.156-35.156Z" fill="#29476b"/><path d="M732.14,991.5c-19.406,0-35.156,15.75-35.156,35.156s15.75,35.156,35.156,35.156s35.156-15.75,35.156-35.156c-.046875-19.406-15.797-35.156-35.156-35.156Z" fill="#29476b"/><path d="M189.1,964.82c-7.2656,0-12.141,4.8281-12.141,12.141v98.203c0,7.2656,4.8281,12.141,12.141,12.141c7.2656,0,12.141-4.8281,12.141-12.141v-98.203c0-7.2656-4.875-12.141-12.141-12.141Z" fill="#29476b"/><path d="M269.11,964.82c-7.2656,0-12.141,4.8281-12.141,12.141v98.203c0,7.2656,4.8281,12.141,12.141,12.141c7.2656,0,12.141-4.8281,12.141-12.141v-98.203c-.046875-7.2656-4.875-12.141-12.141-12.141Z" fill="#29476b"/><path d="M349.08,964.82c-7.2656,0-12.141,4.8281-12.141,12.141v98.203c0,7.2656,4.8281,12.141,12.141,12.141c7.2656,0,12.141-4.8281,12.141-12.141v-98.203c0-7.2656-4.875-12.141-12.141-12.141Z" fill="#29476b"/><path d="M1001.2,616.97c-19.406,0-35.156,15.75-35.156,35.156s15.75,35.156,35.156,35.156s35.156-15.75,35.156-35.156-15.75-35.156-35.156-35.156Z" fill="#3e6962"/><path d="M901.82,652.13c0,46.875-70.312,46.875-70.312,0s70.312-46.875,70.312,0" fill="#3e6962"/><path d="M732.14,616.97c-19.406,0-35.156,15.75-35.156,35.156s15.75,35.156,35.156,35.156s35.156-15.75,35.156-35.156c-.046875-19.406-15.797-35.156-35.156-35.156Z" fill="#3e6962"/><path d="M189.1,590.29c-7.2656,0-12.141,4.8281-12.141,12.141v98.203c0,7.2656,4.8281,12.141,12.141,12.141c7.2656,0,12.141-4.8281,12.141-12.141v-98.203c0-7.2656-4.875-12.141-12.141-12.141Z" fill="#3e6962"/><path d="M269.11,590.29c-7.2656,0-12.141,4.8281-12.141,12.141v98.203c0,7.2656,4.8281,12.141,12.141,12.141c7.2656,0,12.141-4.8281,12.141-12.141v-98.203c-.046875-7.2656-4.875-12.141-12.141-12.141Z" fill="#3e6962"/><path d="M349.08,590.29c-7.2656,0-12.141,4.8281-12.141,12.141v98.203c0,7.2656,4.8281,12.141,12.141,12.141c7.2656,0,12.141-4.8281,12.141-12.141v-98.203c0-7.2656-4.875-12.141-12.141-12.141Z" fill="#3e6962"/><path d="M1001.2,243.66c-19.406,0-35.156,15.75-35.156,35.156s15.75,35.156,35.156,35.156s35.156-15.75,35.156-35.156-15.75-35.156-35.156-35.156Z" fill="#68af51"/><path d="M866.68,243.66c-19.406,0-35.156,15.75-35.156,35.156s15.75,35.156,35.156,35.156s35.156-15.75,35.156-35.156-15.75-35.156-35.156-35.156Z" fill="#68af51"/><path d="M732.14,243.66c-19.406,0-35.156,15.75-35.156,35.156s15.75,35.156,35.156,35.156s35.156-15.75,35.156-35.156c-.046875-19.406-15.797-35.156-35.156-35.156Z" fill="#68af51"/><path d="M189.1,216.98c-7.2656,0-12.141,4.8281-12.141,12.141v98.156c0,7.2656,4.8281,12.141,12.141,12.141c7.2656,0,12.141-4.8281,12.141-12.141v-98.203c0-7.2656-4.875-12.094-12.141-12.094Z" fill="#68af51"/><path d="M269.11,216.98c-7.2656,0-12.141,4.8281-12.141,12.141v98.156c0,7.2656,4.8281,12.141,12.141,12.141c7.2656,0,12.141-4.8281,12.141-12.141v-98.203c-.046875-7.2656-4.875-12.094-12.141-12.094Z" fill="#68af51"/><path d="M349.08,216.98c-7.2656,0-12.141,4.8281-12.141,12.141l.046875,98.156c0,7.2656,4.8281,12.141,12.141,12.141c7.2656,0,12.141-4.8281,12.141-12.141v-98.203c-.046875-7.2656-4.9219-12.094-12.188-12.094h.000125Z" fill="#68af51"/></g><g transform="matrix(.436648 0 0 0.436648-1.425182-165.572402)"><path d="M346.64,1030.4h117.33c3.6094,0,6.6562-2.5312,7.3594-6.0469l19.453-99.844h218.48l19.453,99.844c.70312,3.5625,3.75,6.0469,7.3594,6.0469h117.33c29.953,0,25.969,31.828,25.969,51.938h-558.71c0-20.109-3.9844-51.938,25.969-51.938h.0072Zm764.58-912.74c28.219,0,51.281,23.109,51.281,51.281v679.26c0,28.219-23.109,51.281-51.281,51.281h-1022.4c-28.172,0-51.281-23.062-51.281-51.281v-679.26c0-28.219,23.109-51.281,51.281-51.281h1022.4Zm-17.719,69.703h-987v642.42h987v-642.42Z" transform="matrix(.206263 0 0 0.206262 107.089442 591.077516)" filter="url(#ep4eHtVS5nx23-filter)" fill="#ffb703" fill-rule="evenodd"/><path d="M28.631374,420.431528l203.581581.000001v132.506833h-203.581581v-132.506834Z" transform="translate(100.427249 209.059543)" filter="url(#ep4eHtVS5nx24-filter)" fill="url(#ep4eHtVS5nx24-fill)" stroke-width="4"/><path d="M28.631374,420.431528l203.581581.000001v132.506833h-203.581581v-132.506834Z" transform="translate(100.427249 209.059543)" opacity="0.5" fill="url(#ep4eHtVS5nx25-fill)" stroke-width="4"/></g><g transform="matrix(.436648 0 0 0.436648 266.743208-167.717882)"><path d="M346.64,1030.4h117.33c3.6094,0,6.6562-2.5312,7.3594-6.0469l19.453-99.844h218.48l19.453,99.844c.70312,3.5625,3.75,6.0469,7.3594,6.0469h117.33c29.953,0,25.969,31.828,25.969,51.938h-558.71c0-20.109-3.9844-51.938,25.969-51.938h.0072Zm764.58-912.74c28.219,0,51.281,23.109,51.281,51.281v679.26c0,28.219-23.109,51.281-51.281,51.281h-1022.4c-28.172,0-51.281-23.062-51.281-51.281v-679.26c0-28.219,23.109-51.281,51.281-51.281h1022.4Zm-17.719,69.703h-987v642.42h987v-642.42Z" transform="matrix(.206263 0 0 0.206262 410.868435 591.077516)" filter="url(#ep4eHtVS5nx27-filter)" fill="#219ebc" fill-rule="evenodd"/><path d="M28.631374,420.431528l203.581581.000001v132.506833h-203.581581v-132.506834Z" transform="translate(404.21015 208.860326)" filter="url(#ep4eHtVS5nx28-filter)" fill="url(#ep4eHtVS5nx28-fill)" stroke-width="4"/><path d="M28.631374,420.431528l203.581581.000001v132.506833h-203.581581v-132.506834Z" transform="translate(404.208195 209.059543)" opacity="0.5" fill="url(#ep4eHtVS5nx29-fill)" stroke-width="4"/></g><g><rect width="79.9959" height="50" rx="10" ry="10" transform="translate(259.996852 10)" fill="none" stroke="#7dd049" stroke-width="4"/><text id="ep4eHtVS5nx32" dx="0" dy="0" font-family="&quot;ep4eHtVS5nx1:::Raleway&quot;" font-size="20" font-weight="800" transform="matrix(0 0 0 0 300 33.495738)" fill="#7bce49" stroke-width="0"><tspan y="0" font-weight="800" stroke-width="0"><![CDATA[ 1 - + 0 - + 2 - + 4 - + +1 - + +2 - + +1 - + -1 - + -1 - + +2 - +]]> diff --git a/static/img/diagrams/diag-websocket-handshake.svg b/static/img/diagrams/diag-websocket-handshake.svg index 6563723..5994d2b 100644 --- a/static/img/diagrams/diag-websocket-handshake.svg +++ b/static/img/diagrams/diag-websocket-handshake.svg @@ -1,6 +1,6 @@ - + diff --git a/static/img/diagrams/diag-whiteboard-conflict.svg b/static/img/diagrams/diag-whiteboard-conflict.svg index e554984..8d7b6b1 100644 --- a/static/img/diagrams/diag-whiteboard-conflict.svg +++ b/static/img/diagrams/diag-whiteboard-conflict.svg @@ -1,6 +1,6 @@ - + diff --git a/static/img/diagrams/diag-whiteboard-demo-dual-latency.svg b/static/img/diagrams/diag-whiteboard-demo-dual-latency.svg index 644b29e..7addfa1 100644 --- a/static/img/diagrams/diag-whiteboard-demo-dual-latency.svg +++ b/static/img/diagrams/diag-whiteboard-demo-dual-latency.svg @@ -1,18 +1,18 @@ - +<svg cache-id="6f50b7a462ee4a9bbdda3a0e4f805d71" id="ekotqXwGzLE1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 800 400" shape-rendering="geometricPrecision" text-rendering="geometricPrecision"><defs><filter id="ekotqXwGzLE127-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ekotqXwGzLE127-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="5,5"/><feOffset id="ekotqXwGzLE127-filter-drop-shadow-0-offset" dx="2" dy="2" result="tmp"/><feFlood id="ekotqXwGzLE127-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.3)"/><feComposite id="ekotqXwGzLE127-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ekotqXwGzLE127-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ekotqXwGzLE127-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ekotqXwGzLE127-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><linearGradient id="ekotqXwGzLE127-fill" x1="0.276369" y1="-0.143921" x2="0.482639" y2="1.235259" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="ekotqXwGzLE127-fill-0" offset="0%" stop-color="#fff"/><stop id="ekotqXwGzLE127-fill-1" offset="100%" stop-color="#eee"/></linearGradient><linearGradient id="ekotqXwGzLE127-stroke" x1="0.5" y1="0" x2="0.5" y2="1" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="ekotqXwGzLE127-stroke-0" offset="5%" stop-color="#1d3370"/><stop id="ekotqXwGzLE127-stroke-1" offset="29%" stop-color="#ffba0d"/></linearGradient><filter id="ekotqXwGzLE133-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ekotqXwGzLE133-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="5,5"/><feOffset id="ekotqXwGzLE133-filter-drop-shadow-0-offset" dx="2" dy="2" result="tmp"/><feFlood id="ekotqXwGzLE133-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.3)"/><feComposite id="ekotqXwGzLE133-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ekotqXwGzLE133-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ekotqXwGzLE133-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ekotqXwGzLE133-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><linearGradient id="ekotqXwGzLE133-fill" x1="0.276369" y1="-0.143921" x2="0.482639" y2="1.235259" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="ekotqXwGzLE133-fill-0" offset="0%" stop-color="#fff"/><stop id="ekotqXwGzLE133-fill-1" offset="100%" stop-color="#eee"/></linearGradient><linearGradient id="ekotqXwGzLE133-stroke" x1="0.5" y1="0" x2="0.5" y2="1" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="ekotqXwGzLE133-stroke-0" offset="5%" stop-color="#1d3370"/><stop id="ekotqXwGzLE133-stroke-1" offset="29%" stop-color="#219ebc"/></linearGradient><filter id="ekotqXwGzLE144-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ekotqXwGzLE144-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="ekotqXwGzLE144-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="ekotqXwGzLE144-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="ekotqXwGzLE144-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ekotqXwGzLE144-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ekotqXwGzLE144-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ekotqXwGzLE144-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><radialGradient id="ekotqXwGzLE144-stroke" cx="0" cy="0" r="0.579048" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0.250967 -0.09144)"><stop id="ekotqXwGzLE144-stroke-0" offset="0%" stop-color="#95b8cc"/><stop id="ekotqXwGzLE144-stroke-1" offset="100%" stop-color="#032b43"/></radialGradient><filter id="ekotqXwGzLE146-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ekotqXwGzLE146-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="ekotqXwGzLE146-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="ekotqXwGzLE146-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="ekotqXwGzLE146-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ekotqXwGzLE146-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ekotqXwGzLE146-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ekotqXwGzLE146-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><radialGradient id="ekotqXwGzLE146-stroke" cx="0" cy="0" r="0.579048" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0.250967 -0.09144)"><stop id="ekotqXwGzLE146-stroke-0" offset="0%" stop-color="#95b8cc"/><stop id="ekotqXwGzLE146-stroke-1" offset="100%" stop-color="#032b43"/></radialGradient><filter id="ekotqXwGzLE147-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ekotqXwGzLE147-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="ekotqXwGzLE147-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="ekotqXwGzLE147-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="ekotqXwGzLE147-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ekotqXwGzLE147-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ekotqXwGzLE147-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ekotqXwGzLE147-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><filter id="ekotqXwGzLE156-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ekotqXwGzLE156-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="ekotqXwGzLE156-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="ekotqXwGzLE156-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="ekotqXwGzLE156-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ekotqXwGzLE156-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ekotqXwGzLE156-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ekotqXwGzLE156-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><radialGradient id="ekotqXwGzLE156-stroke" cx="0" cy="0" r="0.579048" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0.250967 -0.09144)"><stop id="ekotqXwGzLE156-stroke-0" offset="0%" stop-color="#95b8cc"/><stop id="ekotqXwGzLE156-stroke-1" offset="100%" stop-color="#032b43"/></radialGradient><filter id="ekotqXwGzLE157-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ekotqXwGzLE157-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="ekotqXwGzLE157-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="ekotqXwGzLE157-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="ekotqXwGzLE157-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ekotqXwGzLE157-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ekotqXwGzLE157-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ekotqXwGzLE157-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><filter id="ekotqXwGzLE161-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ekotqXwGzLE161-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="ekotqXwGzLE161-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="ekotqXwGzLE161-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="ekotqXwGzLE161-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ekotqXwGzLE161-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ekotqXwGzLE161-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ekotqXwGzLE161-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><radialGradient id="ekotqXwGzLE161-stroke" cx="0" cy="0" r="0.579048" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0.250967 -0.09144)"><stop id="ekotqXwGzLE161-stroke-0" offset="0%" stop-color="#95b8cc"/><stop id="ekotqXwGzLE161-stroke-1" offset="100%" stop-color="#032b43"/></radialGradient><filter id="ekotqXwGzLE287-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ekotqXwGzLE287-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="5,5"/><feOffset id="ekotqXwGzLE287-filter-drop-shadow-0-offset" dx="2" dy="2" result="tmp"/><feFlood id="ekotqXwGzLE287-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.3)"/><feComposite id="ekotqXwGzLE287-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ekotqXwGzLE287-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ekotqXwGzLE287-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ekotqXwGzLE287-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><linearGradient id="ekotqXwGzLE287-fill" x1="0.276369" y1="-0.143921" x2="0.482639" y2="1.235259" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="ekotqXwGzLE287-fill-0" offset="0%" stop-color="#fff"/><stop id="ekotqXwGzLE287-fill-1" offset="100%" stop-color="#eee"/></linearGradient><linearGradient id="ekotqXwGzLE287-stroke" x1="0.5" y1="0" x2="0.5" y2="1" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="ekotqXwGzLE287-stroke-0" offset="5%" stop-color="#1d3370"/><stop id="ekotqXwGzLE287-stroke-1" offset="29%" stop-color="#ffba0d"/></linearGradient><filter id="ekotqXwGzLE293-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ekotqXwGzLE293-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="5,5"/><feOffset id="ekotqXwGzLE293-filter-drop-shadow-0-offset" dx="2" dy="2" result="tmp"/><feFlood id="ekotqXwGzLE293-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.3)"/><feComposite id="ekotqXwGzLE293-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ekotqXwGzLE293-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ekotqXwGzLE293-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ekotqXwGzLE293-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><linearGradient id="ekotqXwGzLE293-fill" x1="0.276369" y1="-0.143921" x2="0.482639" y2="1.235259" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="ekotqXwGzLE293-fill-0" offset="0%" stop-color="#fff"/><stop id="ekotqXwGzLE293-fill-1" offset="100%" stop-color="#eee"/></linearGradient><linearGradient id="ekotqXwGzLE293-stroke" x1="0.5" y1="0" x2="0.5" y2="1" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="ekotqXwGzLE293-stroke-0" offset="5%" stop-color="#1d3370"/><stop id="ekotqXwGzLE293-stroke-1" offset="29%" stop-color="#219ebc"/></linearGradient><filter id="ekotqXwGzLE304-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ekotqXwGzLE304-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="ekotqXwGzLE304-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="ekotqXwGzLE304-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="ekotqXwGzLE304-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ekotqXwGzLE304-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ekotqXwGzLE304-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ekotqXwGzLE304-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><radialGradient id="ekotqXwGzLE304-stroke" cx="0" cy="0" r="0.579048" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0.250967 -0.09144)"><stop id="ekotqXwGzLE304-stroke-0" offset="0%" stop-color="#95b8cc"/><stop id="ekotqXwGzLE304-stroke-1" offset="100%" stop-color="#032b43"/></radialGradient><filter id="ekotqXwGzLE306-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ekotqXwGzLE306-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="ekotqXwGzLE306-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="ekotqXwGzLE306-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="ekotqXwGzLE306-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ekotqXwGzLE306-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ekotqXwGzLE306-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ekotqXwGzLE306-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><radialGradient id="ekotqXwGzLE306-stroke" cx="0" cy="0" r="0.579048" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0.250967 -0.09144)"><stop id="ekotqXwGzLE306-stroke-0" offset="0%" stop-color="#95b8cc"/><stop id="ekotqXwGzLE306-stroke-1" offset="100%" stop-color="#032b43"/></radialGradient><filter id="ekotqXwGzLE307-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ekotqXwGzLE307-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="ekotqXwGzLE307-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="ekotqXwGzLE307-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="ekotqXwGzLE307-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ekotqXwGzLE307-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ekotqXwGzLE307-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ekotqXwGzLE307-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><filter id="ekotqXwGzLE316-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ekotqXwGzLE316-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="ekotqXwGzLE316-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="ekotqXwGzLE316-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="ekotqXwGzLE316-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ekotqXwGzLE316-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ekotqXwGzLE316-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ekotqXwGzLE316-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><radialGradient id="ekotqXwGzLE316-stroke" cx="0" cy="0" r="0.579048" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0.250967 -0.09144)"><stop id="ekotqXwGzLE316-stroke-0" offset="0%" stop-color="#95b8cc"/><stop id="ekotqXwGzLE316-stroke-1" offset="100%" stop-color="#032b43"/></radialGradient><filter id="ekotqXwGzLE317-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ekotqXwGzLE317-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="ekotqXwGzLE317-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="ekotqXwGzLE317-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="ekotqXwGzLE317-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ekotqXwGzLE317-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ekotqXwGzLE317-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ekotqXwGzLE317-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><filter id="ekotqXwGzLE321-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="ekotqXwGzLE321-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="ekotqXwGzLE321-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="ekotqXwGzLE321-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="ekotqXwGzLE321-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="ekotqXwGzLE321-filter-drop-shadow-0-merge" result="result"><feMergeNode id="ekotqXwGzLE321-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="ekotqXwGzLE321-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><radialGradient id="ekotqXwGzLE321-stroke" cx="0" cy="0" r="0.579048" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0.250967 -0.09144)"><stop id="ekotqXwGzLE321-stroke-0" offset="0%" stop-color="#95b8cc"/><stop id="ekotqXwGzLE321-stroke-1" offset="100%" stop-color="#032b43"/></radialGradient></defs><g id="ekotqXwGzLE2" transform="translate(0 0.000001)"><g transform="translate(345 172.5)" opacity="0.3" mask="url(#ekotqXwGzLE124)"><g id="ekotqXwGzLE4" transform="translate(-135 0)"><ellipse rx="5" ry="5" transform="translate(165 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(65 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(125 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(25 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(185 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(85 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(145 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-75 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-135 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-35 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-95 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(5 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-155 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-55 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-115 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-15 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-175 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(45 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(105 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(105 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(45 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(145 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(85 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(185 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(25 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(125 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(65 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(165 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(5 5)" fill="#1d3370" stroke-width="0"/></g><g id="ekotqXwGzLE34" transform="translate(-135 40)"><ellipse rx="5" ry="5" transform="translate(165 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(65 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(125 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(25 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(185 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(85 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(145 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-75 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-135 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-35 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-95 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(5 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-155 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-55 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-115 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-15 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-175 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(45 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(105 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(105 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(45 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(145 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(85 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(185 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(25 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(125 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(65 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(165 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(5 5)" fill="#1d3370" stroke-width="0"/></g><g id="ekotqXwGzLE64" transform="translate(185 20)"><ellipse rx="5" ry="5" transform="translate(165 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(65 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(125 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(25 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(185 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(85 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(145 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-75 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-135 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-35 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-95 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(5 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-155 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-55 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-115 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-15 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-175 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(45 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(105 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(105 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(45 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(145 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(85 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(185 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(25 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(125 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(65 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(165 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(5 5)" fill="#1d3370" stroke-width="0"/></g><g id="ekotqXwGzLE94" transform="translate(185 60)"><ellipse rx="5" ry="5" transform="translate(165 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(65 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(125 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(25 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(185 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(85 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(145 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-75 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-135 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-35 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-95 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(5 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-155 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-55 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-115 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-15 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-175 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(45 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(105 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(105 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(45 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(145 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(85 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(185 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(25 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(125 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(65 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(165 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(5 5)" fill="#1d3370" stroke-width="0"/></g><mask id="ekotqXwGzLE124" mask-type="luminance" x="-150%" y="-150%" height="400%" width="400%"><rect width="60" height="70" rx="0" ry="0" fill="#d2dbed" stroke-width="0"/></mask></g><g transform="translate(126.779203 145)"><rect width="300" height="300" rx="15" ry="15" transform="translate(-81.083205-95)" filter="url(#ekotqXwGzLE127-filter)" fill="url(#ekotqXwGzLE127-fill)" stroke="url(#ekotqXwGzLE127-stroke)" stroke-width="5"/><path d="M5,18.887455h300" transform="translate(-86.083205-91.514745)" fill="none" stroke="#344166" stroke-width="2"/><ellipse rx="4" ry="4" transform="translate(-68.476803-82.915981)" fill="none" stroke="#1d3370" stroke-width="2"/><ellipse rx="4" ry="4" transform="translate(-53.476803-82.915981)" fill="none" stroke="#1d3370" stroke-width="2"/><ellipse rx="4" ry="4" transform="translate(-38.476803-82.915981)" fill="none" stroke="#1d3370" stroke-width="2"/></g><g transform="translate(486.083206 145)"><rect width="300" height="300" rx="15" ry="15" transform="translate(-81.083205-95)" filter="url(#ekotqXwGzLE133-filter)" fill="url(#ekotqXwGzLE133-fill)" stroke="url(#ekotqXwGzLE133-stroke)" stroke-width="5"/><path d="M5,18.887455h300" transform="translate(-86.083205-91.514745)" fill="none" stroke="#1d3e78" stroke-width="2"/><ellipse rx="4" ry="4" transform="translate(-68.476803-82.915981)" fill="none" stroke="#1d3370" stroke-width="2"/><ellipse rx="4" ry="4" transform="translate(-53.476803-82.915981)" fill="none" stroke="#1d3370" stroke-width="2"/><ellipse rx="4" ry="4" transform="translate(-38.476803-82.915981)" fill="none" stroke="#1d3370" stroke-width="2"/></g><g><g transform="translate(-7.362429-3.54277)"><rect id="ekotqXwGzLE140" width="70" height="70" rx="0" ry="0" transform="translate(69.601007 104.079071)" fill="#499e4b" stroke="#2c642d" stroke-width="4"/><ellipse id="ekotqXwGzLE141" rx="40" ry="40" transform="matrix(1.1 0 0 1.1 234.932865 134.426203)" fill="#ec7b32" stroke="#82451d" stroke-width="4"/><polygon id="ekotqXwGzLE142" points="0.353966,-45.779297 40.353966,23.500703 -39.646034,23.500703 0.353966,-45.779297" transform="translate(162.640638 275.857824)" fill="#3770e0" stroke="#284d95" stroke-width="3"/></g><g id="ekotqXwGzLE143" transform="translate(-397.46467 117.241217)"><path d="M51.927152,20.916455c3.833523,1.488784,3.54106,6.769614-.435671,7.862724L31.425477,34.294943L22.260793,52.233879c-1.816324,3.555043-7.305874,2.91354-8.173365-.95495L4.745071,9.616763C4.011877,6.34711,7.403427,3.625777,10.6434,4.88401L51.927152,20.916455Z" transform="translate(451.059178 148.471512)" clip-rule="evenodd" filter="url(#ekotqXwGzLE144-filter)" fill="#353b3e" fill-rule="evenodd" stroke="url(#ekotqXwGzLE144-stroke)"/></g><g id="ekotqXwGzLE145" transform="translate(-260.071072 46.958008)"><path d="M51.927152,20.916455c3.833523,1.488784,3.54106,6.769614-.435671,7.862724L31.425477,34.294943L22.260793,52.233879c-1.816324,3.555043-7.305874,2.91354-8.173365-.95495L4.745071,9.616763C4.011877,6.34711,7.403427,3.625777,10.6434,4.88401L51.927152,20.916455Z" transform="translate(451.059178 148.471512)" clip-rule="evenodd" filter="url(#ekotqXwGzLE146-filter)" fill="#219ebc" fill-rule="evenodd" stroke="url(#ekotqXwGzLE146-stroke)"/><rect width="98.548597" height="30.843893" rx="15.42" ry="15.42" transform="translate(491.301616 192.121861)" filter="url(#ekotqXwGzLE147-filter)" fill="#219ebc" stroke="#002a42"/><text dx="0" dy="0" font-family="&quot;ekotqXwGzLE1:::Raleway&quot;" font-size="30" font-weight="500" transform="translate(512.703591 218.141593)" fill="#fff" stroke-width="0"><tspan y="0" font-weight="500" stroke-width="0"><![CDATA[ Bob - + Alice - + Bob - + Alice - +]]> diff --git a/static/img/diagrams/diag-whiteboard-demo-dual.svg b/static/img/diagrams/diag-whiteboard-demo-dual.svg index 4fc6c51..8f14af4 100644 --- a/static/img/diagrams/diag-whiteboard-demo-dual.svg +++ b/static/img/diagrams/diag-whiteboard-demo-dual.svg @@ -1,18 +1,18 @@ - +<svg id="enqzC7Jx93e1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 800 400" shape-rendering="geometricPrecision" text-rendering="geometricPrecision"><defs><filter id="enqzC7Jx93e127-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="enqzC7Jx93e127-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="5,5"/><feOffset id="enqzC7Jx93e127-filter-drop-shadow-0-offset" dx="2" dy="2" result="tmp"/><feFlood id="enqzC7Jx93e127-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.3)"/><feComposite id="enqzC7Jx93e127-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="enqzC7Jx93e127-filter-drop-shadow-0-merge" result="result"><feMergeNode id="enqzC7Jx93e127-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="enqzC7Jx93e127-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><linearGradient id="enqzC7Jx93e127-fill" x1="0.276369" y1="-0.143921" x2="0.482639" y2="1.235259" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="enqzC7Jx93e127-fill-0" offset="0%" stop-color="#fff"/><stop id="enqzC7Jx93e127-fill-1" offset="100%" stop-color="#eee"/></linearGradient><linearGradient id="enqzC7Jx93e127-stroke" x1="0.5" y1="0" x2="0.5" y2="1" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="enqzC7Jx93e127-stroke-0" offset="5%" stop-color="#1d3370"/><stop id="enqzC7Jx93e127-stroke-1" offset="29%" stop-color="#ffba0d"/></linearGradient><filter id="enqzC7Jx93e133-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="enqzC7Jx93e133-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="5,5"/><feOffset id="enqzC7Jx93e133-filter-drop-shadow-0-offset" dx="2" dy="2" result="tmp"/><feFlood id="enqzC7Jx93e133-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.3)"/><feComposite id="enqzC7Jx93e133-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="enqzC7Jx93e133-filter-drop-shadow-0-merge" result="result"><feMergeNode id="enqzC7Jx93e133-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="enqzC7Jx93e133-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><linearGradient id="enqzC7Jx93e133-fill" x1="0.276369" y1="-0.143921" x2="0.482639" y2="1.235259" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="enqzC7Jx93e133-fill-0" offset="0%" stop-color="#fff"/><stop id="enqzC7Jx93e133-fill-1" offset="100%" stop-color="#eee"/></linearGradient><linearGradient id="enqzC7Jx93e133-stroke" x1="0.5" y1="0" x2="0.5" y2="1" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="enqzC7Jx93e133-stroke-0" offset="5%" stop-color="#1d3370"/><stop id="enqzC7Jx93e133-stroke-1" offset="29%" stop-color="#219ebc"/></linearGradient><filter id="enqzC7Jx93e144-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="enqzC7Jx93e144-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="enqzC7Jx93e144-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="enqzC7Jx93e144-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="enqzC7Jx93e144-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="enqzC7Jx93e144-filter-drop-shadow-0-merge" result="result"><feMergeNode id="enqzC7Jx93e144-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="enqzC7Jx93e144-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><radialGradient id="enqzC7Jx93e144-stroke" cx="0" cy="0" r="0.579048" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0.250967 -0.09144)"><stop id="enqzC7Jx93e144-stroke-0" offset="0%" stop-color="#95b8cc"/><stop id="enqzC7Jx93e144-stroke-1" offset="100%" stop-color="#032b43"/></radialGradient><filter id="enqzC7Jx93e146-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="enqzC7Jx93e146-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="enqzC7Jx93e146-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="enqzC7Jx93e146-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="enqzC7Jx93e146-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="enqzC7Jx93e146-filter-drop-shadow-0-merge" result="result"><feMergeNode id="enqzC7Jx93e146-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="enqzC7Jx93e146-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><radialGradient id="enqzC7Jx93e146-stroke" cx="0" cy="0" r="0.579048" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0.250967 -0.09144)"><stop id="enqzC7Jx93e146-stroke-0" offset="0%" stop-color="#95b8cc"/><stop id="enqzC7Jx93e146-stroke-1" offset="100%" stop-color="#032b43"/></radialGradient><filter id="enqzC7Jx93e147-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="enqzC7Jx93e147-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="enqzC7Jx93e147-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="enqzC7Jx93e147-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="enqzC7Jx93e147-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="enqzC7Jx93e147-filter-drop-shadow-0-merge" result="result"><feMergeNode id="enqzC7Jx93e147-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="enqzC7Jx93e147-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><filter id="enqzC7Jx93e156-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="enqzC7Jx93e156-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="enqzC7Jx93e156-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="enqzC7Jx93e156-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="enqzC7Jx93e156-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="enqzC7Jx93e156-filter-drop-shadow-0-merge" result="result"><feMergeNode id="enqzC7Jx93e156-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="enqzC7Jx93e156-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><radialGradient id="enqzC7Jx93e156-stroke" cx="0" cy="0" r="0.579048" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0.250967 -0.09144)"><stop id="enqzC7Jx93e156-stroke-0" offset="0%" stop-color="#95b8cc"/><stop id="enqzC7Jx93e156-stroke-1" offset="100%" stop-color="#032b43"/></radialGradient><filter id="enqzC7Jx93e157-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="enqzC7Jx93e157-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="enqzC7Jx93e157-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="enqzC7Jx93e157-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="enqzC7Jx93e157-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="enqzC7Jx93e157-filter-drop-shadow-0-merge" result="result"><feMergeNode id="enqzC7Jx93e157-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="enqzC7Jx93e157-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><filter id="enqzC7Jx93e161-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="enqzC7Jx93e161-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="enqzC7Jx93e161-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="enqzC7Jx93e161-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="enqzC7Jx93e161-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="enqzC7Jx93e161-filter-drop-shadow-0-merge" result="result"><feMergeNode id="enqzC7Jx93e161-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="enqzC7Jx93e161-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><radialGradient id="enqzC7Jx93e161-stroke" cx="0" cy="0" r="0.579048" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0.250967 -0.09144)"><stop id="enqzC7Jx93e161-stroke-0" offset="0%" stop-color="#95b8cc"/><stop id="enqzC7Jx93e161-stroke-1" offset="100%" stop-color="#032b43"/></radialGradient><filter id="enqzC7Jx93e287-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="enqzC7Jx93e287-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="5,5"/><feOffset id="enqzC7Jx93e287-filter-drop-shadow-0-offset" dx="2" dy="2" result="tmp"/><feFlood id="enqzC7Jx93e287-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.3)"/><feComposite id="enqzC7Jx93e287-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="enqzC7Jx93e287-filter-drop-shadow-0-merge" result="result"><feMergeNode id="enqzC7Jx93e287-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="enqzC7Jx93e287-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><linearGradient id="enqzC7Jx93e287-fill" x1="0.276369" y1="-0.143921" x2="0.482639" y2="1.235259" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="enqzC7Jx93e287-fill-0" offset="0%" stop-color="#fff"/><stop id="enqzC7Jx93e287-fill-1" offset="100%" stop-color="#eee"/></linearGradient><linearGradient id="enqzC7Jx93e287-stroke" x1="0.5" y1="0" x2="0.5" y2="1" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="enqzC7Jx93e287-stroke-0" offset="5%" stop-color="#1d3370"/><stop id="enqzC7Jx93e287-stroke-1" offset="29%" stop-color="#ffba0d"/></linearGradient><filter id="enqzC7Jx93e293-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="enqzC7Jx93e293-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="5,5"/><feOffset id="enqzC7Jx93e293-filter-drop-shadow-0-offset" dx="2" dy="2" result="tmp"/><feFlood id="enqzC7Jx93e293-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.3)"/><feComposite id="enqzC7Jx93e293-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="enqzC7Jx93e293-filter-drop-shadow-0-merge" result="result"><feMergeNode id="enqzC7Jx93e293-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="enqzC7Jx93e293-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><linearGradient id="enqzC7Jx93e293-fill" x1="0.276369" y1="-0.143921" x2="0.482639" y2="1.235259" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="enqzC7Jx93e293-fill-0" offset="0%" stop-color="#fff"/><stop id="enqzC7Jx93e293-fill-1" offset="100%" stop-color="#eee"/></linearGradient><linearGradient id="enqzC7Jx93e293-stroke" x1="0.5" y1="0" x2="0.5" y2="1" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="enqzC7Jx93e293-stroke-0" offset="5%" stop-color="#1d3370"/><stop id="enqzC7Jx93e293-stroke-1" offset="29%" stop-color="#219ebc"/></linearGradient><filter id="enqzC7Jx93e304-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="enqzC7Jx93e304-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="enqzC7Jx93e304-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="enqzC7Jx93e304-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="enqzC7Jx93e304-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="enqzC7Jx93e304-filter-drop-shadow-0-merge" result="result"><feMergeNode id="enqzC7Jx93e304-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="enqzC7Jx93e304-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><radialGradient id="enqzC7Jx93e304-stroke" cx="0" cy="0" r="0.579048" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0.250967 -0.09144)"><stop id="enqzC7Jx93e304-stroke-0" offset="0%" stop-color="#95b8cc"/><stop id="enqzC7Jx93e304-stroke-1" offset="100%" stop-color="#032b43"/></radialGradient><filter id="enqzC7Jx93e306-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="enqzC7Jx93e306-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="enqzC7Jx93e306-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="enqzC7Jx93e306-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="enqzC7Jx93e306-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="enqzC7Jx93e306-filter-drop-shadow-0-merge" result="result"><feMergeNode id="enqzC7Jx93e306-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="enqzC7Jx93e306-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><radialGradient id="enqzC7Jx93e306-stroke" cx="0" cy="0" r="0.579048" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0.250967 -0.09144)"><stop id="enqzC7Jx93e306-stroke-0" offset="0%" stop-color="#95b8cc"/><stop id="enqzC7Jx93e306-stroke-1" offset="100%" stop-color="#032b43"/></radialGradient><filter id="enqzC7Jx93e307-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="enqzC7Jx93e307-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="enqzC7Jx93e307-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="enqzC7Jx93e307-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="enqzC7Jx93e307-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="enqzC7Jx93e307-filter-drop-shadow-0-merge" result="result"><feMergeNode id="enqzC7Jx93e307-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="enqzC7Jx93e307-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><filter id="enqzC7Jx93e316-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="enqzC7Jx93e316-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="enqzC7Jx93e316-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="enqzC7Jx93e316-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="enqzC7Jx93e316-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="enqzC7Jx93e316-filter-drop-shadow-0-merge" result="result"><feMergeNode id="enqzC7Jx93e316-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="enqzC7Jx93e316-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><radialGradient id="enqzC7Jx93e316-stroke" cx="0" cy="0" r="0.579048" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0.250967 -0.09144)"><stop id="enqzC7Jx93e316-stroke-0" offset="0%" stop-color="#95b8cc"/><stop id="enqzC7Jx93e316-stroke-1" offset="100%" stop-color="#032b43"/></radialGradient><filter id="enqzC7Jx93e317-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="enqzC7Jx93e317-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="enqzC7Jx93e317-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="enqzC7Jx93e317-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="enqzC7Jx93e317-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="enqzC7Jx93e317-filter-drop-shadow-0-merge" result="result"><feMergeNode id="enqzC7Jx93e317-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="enqzC7Jx93e317-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><filter id="enqzC7Jx93e321-filter" x="-150%" width="400%" y="-150%" height="400%"><feGaussianBlur id="enqzC7Jx93e321-filter-drop-shadow-0-blur" in="SourceAlpha" stdDeviation="6,6"/><feOffset id="enqzC7Jx93e321-filter-drop-shadow-0-offset" dx="3" dy="3" result="tmp"/><feFlood id="enqzC7Jx93e321-filter-drop-shadow-0-flood" flood-color="rgba(0,0,0,0.25)"/><feComposite id="enqzC7Jx93e321-filter-drop-shadow-0-composite" operator="in" in2="tmp"/><feMerge id="enqzC7Jx93e321-filter-drop-shadow-0-merge" result="result"><feMergeNode id="enqzC7Jx93e321-filter-drop-shadow-0-merge-node-1"/><feMergeNode id="enqzC7Jx93e321-filter-drop-shadow-0-merge-node-2" in="SourceGraphic"/></feMerge></filter><radialGradient id="enqzC7Jx93e321-stroke" cx="0" cy="0" r="0.579048" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0.250967 -0.09144)"><stop id="enqzC7Jx93e321-stroke-0" offset="0%" stop-color="#95b8cc"/><stop id="enqzC7Jx93e321-stroke-1" offset="100%" stop-color="#032b43"/></radialGradient></defs><g id="enqzC7Jx93e2" transform="translate(0 0.000001)"><g transform="translate(345 172.5)" opacity="0.3" mask="url(#enqzC7Jx93e124)"><g id="enqzC7Jx93e4" transform="translate(-135 0)"><ellipse rx="5" ry="5" transform="translate(165 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(65 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(125 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(25 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(185 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(85 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(145 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-75 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-135 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-35 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-95 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(5 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-155 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-55 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-115 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-15 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-175 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(45 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(105 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(105 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(45 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(145 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(85 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(185 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(25 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(125 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(65 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(165 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(5 5)" fill="#1d3370" stroke-width="0"/></g><g id="enqzC7Jx93e34" transform="translate(-135 40)"><ellipse rx="5" ry="5" transform="translate(165 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(65 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(125 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(25 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(185 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(85 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(145 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-75 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-135 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-35 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-95 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(5 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-155 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-55 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-115 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-15 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-175 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(45 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(105 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(105 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(45 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(145 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(85 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(185 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(25 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(125 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(65 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(165 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(5 5)" fill="#1d3370" stroke-width="0"/></g><g id="enqzC7Jx93e64" transform="translate(185 20)"><ellipse rx="5" ry="5" transform="translate(165 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(65 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(125 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(25 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(185 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(85 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(145 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-75 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-135 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-35 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-95 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(5 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-155 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-55 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-115 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-15 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-175 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(45 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(105 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(105 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(45 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(145 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(85 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(185 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(25 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(125 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(65 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(165 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(5 5)" fill="#1d3370" stroke-width="0"/></g><g id="enqzC7Jx93e94" transform="translate(185 60)"><ellipse rx="5" ry="5" transform="translate(165 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(65 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(125 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(25 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(185 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(85 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(145 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-75 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-135 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-35 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-95 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(5 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-155 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-55 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-115 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-15 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(-175 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(45 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(105 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(105 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(45 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(145 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(85 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(185 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(25 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(125 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(65 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(165 5)" fill="#1d3370" stroke-width="0"/><ellipse rx="5" ry="5" transform="translate(5 5)" fill="#1d3370" stroke-width="0"/></g><mask id="enqzC7Jx93e124" mask-type="luminance" x="-150%" y="-150%" height="400%" width="400%"><rect width="60" height="70" rx="0" ry="0" fill="#d2dbed" stroke-width="0"/></mask></g><g transform="translate(126.779203 145)"><rect width="300" height="300" rx="15" ry="15" transform="translate(-81.083205-95)" filter="url(#enqzC7Jx93e127-filter)" fill="url(#enqzC7Jx93e127-fill)" stroke="url(#enqzC7Jx93e127-stroke)" stroke-width="5"/><path d="M5,18.887455h300" transform="translate(-86.083205-91.514745)" fill="none" stroke="#344166" stroke-width="2"/><ellipse rx="4" ry="4" transform="translate(-68.476803-82.915981)" fill="none" stroke="#1d3370" stroke-width="2"/><ellipse rx="4" ry="4" transform="translate(-53.476803-82.915981)" fill="none" stroke="#1d3370" stroke-width="2"/><ellipse rx="4" ry="4" transform="translate(-38.476803-82.915981)" fill="none" stroke="#1d3370" stroke-width="2"/></g><g transform="translate(486.083206 145)"><rect width="300" height="300" rx="15" ry="15" transform="translate(-81.083205-95)" filter="url(#enqzC7Jx93e133-filter)" fill="url(#enqzC7Jx93e133-fill)" stroke="url(#enqzC7Jx93e133-stroke)" stroke-width="5"/><path d="M5,18.887455h300" transform="translate(-86.083205-91.514745)" fill="none" stroke="#1d3e78" stroke-width="2"/><ellipse rx="4" ry="4" transform="translate(-68.476803-82.915981)" fill="none" stroke="#1d3370" stroke-width="2"/><ellipse rx="4" ry="4" transform="translate(-53.476803-82.915981)" fill="none" stroke="#1d3370" stroke-width="2"/><ellipse rx="4" ry="4" transform="translate(-38.476803-82.915981)" fill="none" stroke="#1d3370" stroke-width="2"/></g><g><g transform="translate(-7.362429-3.54277)"><rect id="enqzC7Jx93e140" width="70" height="70" rx="0" ry="0" transform="translate(69.601007 104.079071)" fill="#499e4b" stroke="#2c642d" stroke-width="4"/><ellipse id="enqzC7Jx93e141" rx="40" ry="40" transform="matrix(1.1 0 0 1.1 234.932865 134.426203)" fill="#ec7b32" stroke="#82451d" stroke-width="4"/><polygon id="enqzC7Jx93e142" points="0.353966,-45.779297 40.353966,23.500703 -39.646034,23.500703 0.353966,-45.779297" transform="translate(162.640638 275.857824)" fill="#3770e0" stroke="#284d95" stroke-width="3"/></g><g id="enqzC7Jx93e143" transform="translate(-397.46467 117.241217)"><path d="M51.927152,20.916455c3.833523,1.488784,3.54106,6.769614-.435671,7.862724L31.425477,34.294943L22.260793,52.233879c-1.816324,3.555043-7.305874,2.91354-8.173365-.95495L4.745071,9.616763C4.011877,6.34711,7.403427,3.625777,10.6434,4.88401L51.927152,20.916455Z" transform="translate(451.059178 148.471512)" clip-rule="evenodd" filter="url(#enqzC7Jx93e144-filter)" fill="#353b3e" fill-rule="evenodd" stroke="url(#enqzC7Jx93e144-stroke)"/></g><g id="enqzC7Jx93e145" transform="translate(-260.071072 46.958008)"><path d="M51.927152,20.916455c3.833523,1.488784,3.54106,6.769614-.435671,7.862724L31.425477,34.294943L22.260793,52.233879c-1.816324,3.555043-7.305874,2.91354-8.173365-.95495L4.745071,9.616763C4.011877,6.34711,7.403427,3.625777,10.6434,4.88401L51.927152,20.916455Z" transform="translate(451.059178 148.471512)" clip-rule="evenodd" filter="url(#enqzC7Jx93e146-filter)" fill="#219ebc" fill-rule="evenodd" stroke="url(#enqzC7Jx93e146-stroke)"/><rect width="98.548597" height="30.843893" rx="15.42" ry="15.42" transform="translate(491.301616 192.121861)" filter="url(#enqzC7Jx93e147-filter)" fill="#219ebc" stroke="#002a42"/><text dx="0" dy="0" font-family="&quot;enqzC7Jx93e1:::Raleway&quot;" font-size="30" font-weight="500" transform="translate(512.703591 218.141593)" fill="#fff" stroke-width="0"><tspan y="0" font-weight="500" stroke-width="0"><![CDATA[ Bob - + Alice - + Bob - + Alice - +]]> diff --git a/tailwind.config.js b/tailwind.config.js index ac14698..b897dcd 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -2,7 +2,7 @@ const { fontFamily } = require('tailwindcss/defaultTheme') /** @type {import('tailwindcss').Config} */ module.exports = { - content: ["./src/**/*.{js,jsx,ts,tsx}"], + content: ['./src/**/*.{js,jsx,ts,tsx}'], corePlugins: { preflight: false, container: false, From 86cb5b0fa406eebe45e4c8aa2315972bda858443 Mon Sep 17 00:00:00 2001 From: Alex Sklar Date: Wed, 24 Apr 2024 16:27:15 -0700 Subject: [PATCH 06/12] feat(diag): add diagram coloring Co-authored-by: Erik Margetis Co-authored-by: Joseph Liang --- src/pages/case-study.mdx | 6 +----- static/img/diagrams/diag-DeltaUpdates.svg | 4 ++-- static/img/diagrams/diag-ON-messaging.svg | 4 ++-- static/img/diagrams/diag-ON2-messaging.svg | 4 ++-- static/img/diagrams/diag-StateUpdates.svg | 4 ++-- static/img/diagrams/diag-syncingModel-1.svg | 4 ++-- static/img/diagrams/diag-syncingModel-3.svg | 4 ++-- static/img/diagrams/diag-syncingModel-4.svg | 4 ++-- static/img/diagrams/diag-timeDrivenMessages.svg | 4 ++-- 9 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/pages/case-study.mdx b/src/pages/case-study.mdx index 28ab683..2e03b65 100644 --- a/src/pages/case-study.mdx +++ b/src/pages/case-study.mdx @@ -331,13 +331,9 @@ As mentioned, Syncosaurus uses a real-time syncing model with transactional conf - When a client makes a change to state, it is immediately applied to the client’s locally and the client places a copy of the intent of the change (i.e. a state mutation) in a pending queue. - - -- Next, the mutation is sent across the WebSocket connection to the Syncosaurus server. - -- Once the change is made to the authoritative state, the server sends a confirmation update to the client, which the client then uses to update its state to match the server and remove the pending state mutation from the queue. +- Next, the mutation is sent across the WebSocket connection to the Syncosaurus server. Once the change is made to the authoritative state, the server sends a confirmation update to the client, which the client then uses to update its state to match the server and remove the pending state mutation from the queue. diff --git a/static/img/diagrams/diag-DeltaUpdates.svg b/static/img/diagrams/diag-DeltaUpdates.svg index 00131dd..6384dbe 100644 --- a/static/img/diagrams/diag-DeltaUpdates.svg +++ b/static/img/diagrams/diag-DeltaUpdates.svg @@ -1,6 +1,6 @@ - + diff --git a/static/img/diagrams/diag-ON-messaging.svg b/static/img/diagrams/diag-ON-messaging.svg index fc50d39..c43515a 100644 --- a/static/img/diagrams/diag-ON-messaging.svg +++ b/static/img/diagrams/diag-ON-messaging.svg @@ -1,6 +1,6 @@ - + diff --git a/static/img/diagrams/diag-ON2-messaging.svg b/static/img/diagrams/diag-ON2-messaging.svg index 58c651c..8f5b9a4 100644 --- a/static/img/diagrams/diag-ON2-messaging.svg +++ b/static/img/diagrams/diag-ON2-messaging.svg @@ -1,6 +1,6 @@ - + diff --git a/static/img/diagrams/diag-StateUpdates.svg b/static/img/diagrams/diag-StateUpdates.svg index 1635de4..b06a9aa 100644 --- a/static/img/diagrams/diag-StateUpdates.svg +++ b/static/img/diagrams/diag-StateUpdates.svg @@ -1,6 +1,6 @@ - + diff --git a/static/img/diagrams/diag-syncingModel-1.svg b/static/img/diagrams/diag-syncingModel-1.svg index b5a64e6..e0fd75d 100644 --- a/static/img/diagrams/diag-syncingModel-1.svg +++ b/static/img/diagrams/diag-syncingModel-1.svg @@ -1,6 +1,6 @@ - + diff --git a/static/img/diagrams/diag-syncingModel-3.svg b/static/img/diagrams/diag-syncingModel-3.svg index 0ba075c..c4ff628 100644 --- a/static/img/diagrams/diag-syncingModel-3.svg +++ b/static/img/diagrams/diag-syncingModel-3.svg @@ -1,6 +1,6 @@ - + diff --git a/static/img/diagrams/diag-syncingModel-4.svg b/static/img/diagrams/diag-syncingModel-4.svg index f556055..297c6fe 100644 --- a/static/img/diagrams/diag-syncingModel-4.svg +++ b/static/img/diagrams/diag-syncingModel-4.svg @@ -1,6 +1,6 @@ - + diff --git a/static/img/diagrams/diag-timeDrivenMessages.svg b/static/img/diagrams/diag-timeDrivenMessages.svg index 97563c8..172846a 100644 --- a/static/img/diagrams/diag-timeDrivenMessages.svg +++ b/static/img/diagrams/diag-timeDrivenMessages.svg @@ -1,6 +1,6 @@ - + From d87ca78d49c298fc5b05fe858d7e52f3493c1725 Mon Sep 17 00:00:00 2001 From: Alex Sklar Date: Wed, 24 Apr 2024 16:34:28 -0700 Subject: [PATCH 07/12] feat(diag): add messaging diagram styling Co-authored-by: Erik Margetis Co-authored-by: Joseph Liang --- static/img/diagrams/diag-ON-messaging.svg | 4 ++-- static/img/diagrams/diag-timeDrivenMessages.svg | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/static/img/diagrams/diag-ON-messaging.svg b/static/img/diagrams/diag-ON-messaging.svg index c43515a..1e72866 100644 --- a/static/img/diagrams/diag-ON-messaging.svg +++ b/static/img/diagrams/diag-ON-messaging.svg @@ -1,6 +1,6 @@ - + diff --git a/static/img/diagrams/diag-timeDrivenMessages.svg b/static/img/diagrams/diag-timeDrivenMessages.svg index 172846a..ace8136 100644 --- a/static/img/diagrams/diag-timeDrivenMessages.svg +++ b/static/img/diagrams/diag-timeDrivenMessages.svg @@ -1,4 +1,4 @@ - +