add pw-frontend
2
web/pw-frontend/.editorconfig
Normal file
|
@ -0,0 +1,2 @@
|
|||
[*.{js,ts,html,svelte}]
|
||||
indent_size = 2
|
5
web/pw-frontend/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
/node_modules/
|
||||
/dist/
|
||||
/.vscode/
|
||||
.DS_Store
|
||||
package-lock.json
|
48
web/pw-frontend/README.md
Normal file
|
@ -0,0 +1,48 @@
|
|||
# Svelte + TS + Vite
|
||||
|
||||
This template should help get you started developing with Svelte and TypeScript in Vite.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).
|
||||
|
||||
## Need an official Svelte framework?
|
||||
|
||||
Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.
|
||||
|
||||
## Technical considerations
|
||||
|
||||
**Why use this over SvelteKit?**
|
||||
|
||||
- It brings its own routing solution which might not be preferable for some users.
|
||||
- It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.
|
||||
`vite dev` and `vite build` wouldn't work in a SvelteKit environment, for example.
|
||||
|
||||
This template contains as little as possible to get started with Vite + TypeScript + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.
|
||||
|
||||
Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.
|
||||
|
||||
**Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?**
|
||||
|
||||
Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information.
|
||||
|
||||
**Why include `.vscode/extensions.json`?**
|
||||
|
||||
Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.
|
||||
|
||||
**Why enable `allowJs` in the TS template?**
|
||||
|
||||
While `allowJs: false` would indeed prevent the use of `.js` files in the project, it does not prevent the use of JavaScript syntax in `.svelte` files. In addition, it would force `checkJs: false`, bringing the worst of both worlds: not being able to guarantee the entire codebase is TypeScript, and also having worse typechecking for the existing JavaScript. In addition, there are valid use cases in which a mixed codebase may be relevant.
|
||||
|
||||
**Why is HMR not preserving my local component state?**
|
||||
|
||||
HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr).
|
||||
|
||||
If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.
|
||||
|
||||
```ts
|
||||
// store.ts
|
||||
// An extremely simple external store
|
||||
import { writable } from 'svelte/store'
|
||||
export default writable(0)
|
||||
```
|
19
web/pw-frontend/index.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!-- polyfill global -->
|
||||
<script>
|
||||
const global = globalThis;
|
||||
</script>
|
||||
<!-- end polyfill -->
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Planetwars</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
30
web/pw-frontend/package.json
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "pw-frontend",
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-check --tsconfig ./tsconfig.json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.30",
|
||||
"@tsconfig/svelte": "^2.0.1",
|
||||
"rollup-plugin-polyfill-node": "^0.8.0",
|
||||
"svelte": "^3.44.0",
|
||||
"svelte-check": "^2.2.7",
|
||||
"svelte-preprocess": "^4.9.8",
|
||||
"tslib": "^2.3.1",
|
||||
"typescript": "^4.4.4",
|
||||
"vite": "^2.7.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"buffer": "^6.0.3",
|
||||
"extract-svg-path": "^2.1.0",
|
||||
"load-svg": "^1.0.0",
|
||||
"planetwars-rs": "file:./planetwars-rs/pkg",
|
||||
"svg-mesh-3d": "^1.1.0",
|
||||
"ts-heap": "^1.1.3"
|
||||
}
|
||||
}
|
2
web/pw-frontend/planetwars-rs/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
pkg/**
|
||||
target/**
|
44
web/pw-frontend/planetwars-rs/Cargo.toml
Normal file
|
@ -0,0 +1,44 @@
|
|||
[package]
|
||||
name = "planetwars-rs"
|
||||
version = "0.1.0"
|
||||
authors = ["ajuvercr <arthur.vercruysse@ugent.be>"]
|
||||
edition = "2018"
|
||||
|
||||
[package.metadata.wasm-pack.profile.release]
|
||||
wasm-opt = ["-Oz", "--enable-mutable-globals"]
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2"
|
||||
|
||||
# The `console_error_panic_hook` crate provides better debugging of panics by
|
||||
# logging them with `console.error`. This is great for development, but requires
|
||||
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
|
||||
# code size when deploying.
|
||||
console_error_panic_hook = { version = "0.1.1", optional = true }
|
||||
|
||||
# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size
|
||||
# compared to the default allocator's ~10K. It is slower than the default
|
||||
# allocator, however.
|
||||
#
|
||||
# Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now.
|
||||
wee_alloc = { version = "0.4.2", optional = true }
|
||||
serde = "1.0.100"
|
||||
serde_derive = "1.0.100"
|
||||
serde_json = "1.0"
|
||||
octoon-math = "0.1.7"
|
||||
voronoi = "0.1.4"
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.2"
|
||||
|
||||
[profile.release]
|
||||
# Tell `rustc` to optimize for small code size.
|
||||
opt-level = "s"
|
||||
|
||||
[workspace]
|
373
web/pw-frontend/planetwars-rs/src/lib.rs
Normal file
|
@ -0,0 +1,373 @@
|
|||
extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate octoon_math;
|
||||
extern crate serde_json;
|
||||
extern crate voronoi;
|
||||
|
||||
use octoon_math::Mat3;
|
||||
use voronoi::{make_polygons, voronoi, Point};
|
||||
|
||||
mod types;
|
||||
mod utils;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
macro_rules! console_log {
|
||||
// Note that this is using the `log` function imported above during
|
||||
// `bare_bones`
|
||||
($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
|
||||
}
|
||||
|
||||
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
|
||||
// allocator.
|
||||
#[cfg(feature = "wee_alloc")]
|
||||
#[global_allocator]
|
||||
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Circle {
|
||||
r: f32,
|
||||
x: f32,
|
||||
y: f32,
|
||||
a0: f32,
|
||||
ad: f32,
|
||||
distance: usize,
|
||||
}
|
||||
|
||||
use std::f32::consts::PI;
|
||||
fn spr(from: f32) -> f32 {
|
||||
let pi2 = PI * 2.;
|
||||
((from % pi2) + pi2) % pi2
|
||||
}
|
||||
|
||||
impl Circle {
|
||||
pub fn new(p1: &types::Planet, p2: &types::Planet) -> Self {
|
||||
let x1 = p1.x;
|
||||
let y1 = p1.y;
|
||||
let x2 = p2.x;
|
||||
let y2 = p2.y;
|
||||
|
||||
// Distance between planets
|
||||
let q = ((x2 - x1).powi(2) + (y2 - y1).powi(2)).sqrt();
|
||||
// Center of between planets
|
||||
let x3 = (x1 + x2) / 2.0;
|
||||
let y3 = (y1 + y2) / 2.0;
|
||||
|
||||
// Radius of circle
|
||||
let r = q * 1.0;
|
||||
|
||||
// Center of circle
|
||||
let x = x3 + (r.powi(2) - (q / 2.0).powi(2)).sqrt() * (y1 - y2) / q;
|
||||
let y = y3 + (r.powi(2) - (q / 2.0).powi(2)).sqrt() * (x2 - x1) / q;
|
||||
// console_log!("{},{} -> {},{} ({},{} r={})", x1, y1, x2, y2, x, y, r);
|
||||
|
||||
let a0 = spr((y - y1).atan2(x - x1));
|
||||
let a2 = spr((y - y2).atan2(x - x2));
|
||||
|
||||
let mut ad = spr(a0 - a2);
|
||||
if ad > PI {
|
||||
ad = spr(a2 - a0);
|
||||
}
|
||||
// console_log!("a1 {} a2 {} ad {}", a0/PI * 180.0, a2/PI * 180.0, ad/PI*180.0);
|
||||
|
||||
let distance = q.ceil() as usize + 1;
|
||||
Self {
|
||||
r,
|
||||
x,
|
||||
y,
|
||||
a0,
|
||||
ad,
|
||||
distance,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_for_remaining(&self, remaining: usize) -> ((Mat3<f32>, f32), (Mat3<f32>, f32)) {
|
||||
(
|
||||
self.get_remaining(remaining),
|
||||
self.get_remaining((remaining + 1).min(self.distance - 1)),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_remaining(&self, remaining: usize) -> (Mat3<f32>, f32) {
|
||||
let alpha = self.a0 + (1.0 - (remaining as f32 / self.distance as f32)) * self.ad;
|
||||
|
||||
let cos = alpha.cos();
|
||||
let sin = alpha.sin();
|
||||
(
|
||||
Mat3::new(
|
||||
0.3,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.3,
|
||||
0.0,
|
||||
-self.x + cos * self.r,
|
||||
-self.y + sin * self.r,
|
||||
0.3,
|
||||
),
|
||||
alpha,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn create_voronoi(planets: &Vec<types::Planet>, bbox: f32) -> (Vec<f32>, Vec<usize>) {
|
||||
let mut verts: Vec<[f32; 2]> = planets.iter().map(|p| [p.x, p.y]).collect();
|
||||
let mut ids = Vec::new();
|
||||
|
||||
let vor_points = planets
|
||||
.iter()
|
||||
.map(|p| Point::new(p.x as f64, p.y as f64))
|
||||
.collect();
|
||||
|
||||
let vor = voronoi(vor_points, bbox as f64);
|
||||
let vor = make_polygons(&vor);
|
||||
|
||||
for poly in vor.iter() {
|
||||
// Get planet index for planet that is inside this poligon
|
||||
let idx = 0;
|
||||
|
||||
let mut prev = ids.len() + poly.len() - 1;
|
||||
for p in poly.iter() {
|
||||
let now = verts.len();
|
||||
verts.push([p.x.0 as f32, p.y.0 as f32]);
|
||||
|
||||
ids.push(idx);
|
||||
ids.push(now);
|
||||
ids.push(prev);
|
||||
prev = now;
|
||||
}
|
||||
}
|
||||
|
||||
(verts.concat(), ids)
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct Game {
|
||||
states: Vec<types::State>,
|
||||
turn: usize,
|
||||
|
||||
planet_map: HashMap<(String, String), Circle>,
|
||||
|
||||
/* put extra shit here */
|
||||
view_box: Vec<f32>,
|
||||
|
||||
planets: Vec<f32>,
|
||||
planet_ships: Vec<usize>,
|
||||
|
||||
ship_locations: Vec<f32>,
|
||||
ship_label_locations: Vec<f32>,
|
||||
ship_colours: Vec<f32>,
|
||||
ship_counts: Vec<usize>,
|
||||
|
||||
current_planet_colours: Vec<f32>,
|
||||
|
||||
voronoi_vertices: Vec<f32>,
|
||||
voronoi_colors: Vec<f32>,
|
||||
voronoi_indices: Vec<usize>,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl Game {
|
||||
pub fn new(file: &str) -> Self {
|
||||
utils::set_panic_hook();
|
||||
|
||||
// First line is fucked but we just filter out things that cannot parse
|
||||
let states: Vec<types::State> = file
|
||||
.split("\n")
|
||||
.filter_map(|line| serde_json::from_str(line).ok())
|
||||
.collect();
|
||||
|
||||
let mut planet_map = HashMap::new();
|
||||
|
||||
// Iterator?
|
||||
for p1 in states[0].planets.iter() {
|
||||
for p2 in states[0].planets.iter() {
|
||||
planet_map.insert((p1.name.clone(), p2.name.clone()), Circle::new(&p1, &p2));
|
||||
}
|
||||
}
|
||||
let view_box = utils::caclulate_viewbox(&states[0].planets);
|
||||
|
||||
let (voronoi_vertices, voronoi_indices) =
|
||||
create_voronoi(&states[0].planets, view_box[2].max(view_box[3]));
|
||||
|
||||
let voronoi_colors: Vec<f32> = voronoi_indices
|
||||
.iter()
|
||||
.map(|_| [0.0, 0.0, 0.0])
|
||||
.collect::<Vec<[f32; 3]>>()
|
||||
.concat(); // Init these colours on black
|
||||
|
||||
Self {
|
||||
planets: utils::get_planets(&states[0].planets, 2.0),
|
||||
planet_ships: Vec::new(),
|
||||
view_box,
|
||||
|
||||
planet_map,
|
||||
turn: 0,
|
||||
states,
|
||||
ship_locations: Vec::new(),
|
||||
ship_label_locations: Vec::new(),
|
||||
ship_colours: Vec::new(),
|
||||
ship_counts: Vec::new(),
|
||||
current_planet_colours: Vec::new(),
|
||||
|
||||
voronoi_vertices,
|
||||
voronoi_indices,
|
||||
voronoi_colors,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_state(&mut self, state_str: &str) {
|
||||
if let Ok(state) = serde_json::from_str(state_str) {
|
||||
self.states.push(state);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_viewbox(&self) -> Vec<f32> {
|
||||
self.view_box.clone()
|
||||
}
|
||||
|
||||
pub fn get_planets(&self) -> Vec<f32> {
|
||||
self.planets.clone()
|
||||
}
|
||||
|
||||
pub fn get_planet_ships(&self) -> Vec<usize> {
|
||||
self.planet_ships.clone()
|
||||
}
|
||||
|
||||
pub fn get_planet_colors(&self) -> Vec<f32> {
|
||||
self.current_planet_colours.clone()
|
||||
}
|
||||
|
||||
pub fn turn_count(&self) -> usize {
|
||||
self.states.len()
|
||||
}
|
||||
|
||||
pub fn update_turn(&mut self, turn: usize) -> usize {
|
||||
self.turn = turn.min(self.states.len() - 1);
|
||||
|
||||
self.update_planet_ships();
|
||||
self.update_planet_colours();
|
||||
self.update_voronoi_colors();
|
||||
self.update_ship_locations();
|
||||
self.update_ship_counts();
|
||||
|
||||
self.turn
|
||||
}
|
||||
|
||||
fn update_planet_ships(&mut self) {
|
||||
self.planet_ships = self.states[self.turn]
|
||||
.planets
|
||||
.iter()
|
||||
.map(|p| p.ship_count as usize)
|
||||
.collect();
|
||||
}
|
||||
|
||||
fn update_voronoi_colors(&mut self) {
|
||||
for (i, p) in self.states[self.turn].planets.iter().enumerate() {
|
||||
let color = utils::COLORS[p.owner.unwrap_or(0) as usize % utils::COLORS.len()];
|
||||
self.voronoi_colors[i * 3 + 0] = color[0];
|
||||
self.voronoi_colors[i * 3 + 1] = color[1];
|
||||
self.voronoi_colors[i * 3 + 2] = color[2];
|
||||
}
|
||||
}
|
||||
|
||||
fn update_planet_colours(&mut self) {
|
||||
let mut new_vec: Vec<[f32; 3]> = Vec::new();
|
||||
let planets_now = self.states[self.turn].planets.iter();
|
||||
let planets_later = self.states[(self.turn + 1).min(self.states.len() - 1)]
|
||||
.planets
|
||||
.iter();
|
||||
|
||||
for (p1, p2) in planets_now.zip(planets_later) {
|
||||
new_vec
|
||||
.push(utils::COLORS[p1.owner.unwrap_or(0) as usize % utils::COLORS.len()].into());
|
||||
new_vec
|
||||
.push(utils::COLORS[p2.owner.unwrap_or(0) as usize % utils::COLORS.len()].into());
|
||||
}
|
||||
|
||||
self.current_planet_colours = new_vec.concat::<f32>();
|
||||
}
|
||||
|
||||
fn update_ship_locations(&mut self) {
|
||||
let mut new_sl = Vec::new();
|
||||
let mut new_sll = Vec::new();
|
||||
|
||||
let t = Mat3::new(0.2, 0., 0., 0., 0.2, 0.0, 0., -0.5, 0.2);
|
||||
|
||||
for ship in self.states[self.turn].expeditions.iter() {
|
||||
let ((o1, a1), (o2, a2)) = self
|
||||
.planet_map
|
||||
.get(&(ship.origin.clone(), ship.destination.clone()))
|
||||
.unwrap()
|
||||
.get_for_remaining(ship.turns_remaining as usize);
|
||||
new_sl.push((o1 * Mat3::rotate_z(a1)).to_array());
|
||||
new_sl.push((o2 * Mat3::rotate_z(a2)).to_array());
|
||||
|
||||
new_sll.push((o1 + t).to_array());
|
||||
new_sll.push((o2 + t).to_array());
|
||||
}
|
||||
|
||||
self.ship_locations = new_sl.concat();
|
||||
self.ship_label_locations = new_sll.concat();
|
||||
|
||||
self.ship_colours = self.states[self.turn]
|
||||
.expeditions
|
||||
.iter()
|
||||
.map(|s| utils::COLORS[s.owner as usize % utils::COLORS.len()])
|
||||
.collect::<Vec<[f32; 3]>>()
|
||||
.concat();
|
||||
}
|
||||
|
||||
fn update_ship_counts(&mut self) {
|
||||
self.ship_counts = self.states[self.turn]
|
||||
.expeditions
|
||||
.iter()
|
||||
.map(|s| s.ship_count as usize)
|
||||
.collect();
|
||||
}
|
||||
|
||||
pub fn get_max_ships(&self) -> usize {
|
||||
self.states
|
||||
.iter()
|
||||
.map(|s| s.expeditions.len())
|
||||
.max()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn get_ship_locations(&self) -> Vec<f32> {
|
||||
self.ship_locations.clone()
|
||||
}
|
||||
|
||||
pub fn get_ship_label_locations(&self) -> Vec<f32> {
|
||||
self.ship_label_locations.clone()
|
||||
}
|
||||
|
||||
pub fn get_ship_colours(&self) -> Vec<f32> {
|
||||
self.ship_colours.clone()
|
||||
}
|
||||
|
||||
pub fn get_ship_counts(&self) -> Vec<usize> {
|
||||
self.ship_counts.clone()
|
||||
}
|
||||
|
||||
pub fn get_voronoi_verts(&self) -> Vec<f32> {
|
||||
self.voronoi_vertices.clone()
|
||||
}
|
||||
|
||||
pub fn get_voronoi_colours(&self) -> Vec<f32> {
|
||||
self.voronoi_colors.clone()
|
||||
}
|
||||
|
||||
pub fn get_voronoi_inds(&self) -> Vec<usize> {
|
||||
self.voronoi_indices.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
fn alert(s: &str);
|
||||
#[wasm_bindgen(js_namespace = console)]
|
||||
fn log(s: &str);
|
||||
}
|
45
web/pw-frontend/planetwars-rs/src/types.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Expedition {
|
||||
pub id: u64,
|
||||
pub ship_count: u64,
|
||||
pub origin: String,
|
||||
pub destination: String,
|
||||
pub owner: u64,
|
||||
pub turns_remaining: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Planet {
|
||||
pub ship_count: u64,
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub owner: Option<u32>,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::mem;
|
||||
|
||||
impl Hash for Planet {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
unsafe {
|
||||
let x: u32 = mem::transmute_copy(&self.x);
|
||||
let y: u32 = mem::transmute_copy(&self.y);
|
||||
state.write_u32(x);
|
||||
state.write_u32(y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Planet {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
(self.x - other.x).abs() < 0.0001 && (self.y - other.y).abs() < 0.0001
|
||||
}
|
||||
}
|
||||
impl Eq for Planet {}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct State {
|
||||
pub planets: Vec<Planet>,
|
||||
pub expeditions: Vec<Expedition>,
|
||||
}
|
65
web/pw-frontend/planetwars-rs/src/utils.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
pub fn set_panic_hook() {
|
||||
// When the `console_error_panic_hook` feature is enabled, we can call the
|
||||
// `set_panic_hook` function at least once during initialization, and then
|
||||
// we will get better error messages if our code ever panics.
|
||||
//
|
||||
// For more details see
|
||||
// https://github.com/rustwasm/console_error_panic_hook#readme
|
||||
#[cfg(feature = "console_error_panic_hook")]
|
||||
console_error_panic_hook::set_once();
|
||||
}
|
||||
|
||||
/// this is total extra, so it the planet viewbox is like 100px wide, it will now be in total 110 pixels wide
|
||||
static VIEWBOX_SCALE: f32 = 0.1;
|
||||
|
||||
pub static COLORS: [[f32; 3]; 10] = [
|
||||
[0.5, 0.5, 0.5],
|
||||
[1.0, 0.50, 0.0], // #FF8000
|
||||
[0.0, 0.50, 1.0], // #0080ff
|
||||
[1.0, 0.4, 0.58], // #FF6693
|
||||
[0.24, 0.79, 0.33], // #3fcb55
|
||||
[0.79, 0.76, 0.24], // #cbc33f
|
||||
[0.81, 0.25, 0.91], // #cf40e9
|
||||
[0.94, 0.32, 0.32], // #FF3F0D
|
||||
[0.11, 0.93, 0.94], // #1beef0
|
||||
[0.05, 0.77, 1.0], // #0DC5FF
|
||||
];
|
||||
|
||||
use super::types;
|
||||
|
||||
pub fn caclulate_viewbox(planets: &Vec<types::Planet>) -> Vec<f32> {
|
||||
let mut iter = planets.iter();
|
||||
|
||||
let init = match iter.next() {
|
||||
Some(p) => (p.x, p.y, p.x, p.y),
|
||||
None => return vec![0.0, 0.0, 0.0, 0.0],
|
||||
};
|
||||
let (min_x, min_y, max_x, max_y) =
|
||||
planets
|
||||
.iter()
|
||||
.fold(init, |(min_x, min_y, max_x, max_y), p| {
|
||||
(
|
||||
min_x.min(p.x),
|
||||
min_y.min(p.y),
|
||||
max_x.max(p.x),
|
||||
max_y.max(p.y),
|
||||
)
|
||||
});
|
||||
|
||||
let (width, height) = (max_x - min_x, max_y - min_y);
|
||||
let (dx, dy) = (
|
||||
(VIEWBOX_SCALE * width).max(6.0),
|
||||
(VIEWBOX_SCALE * height).max(6.0),
|
||||
);
|
||||
|
||||
vec![min_x - dx / 2.0, min_y - dy / 2.0, width + dx, height + dy]
|
||||
}
|
||||
|
||||
pub fn get_planets(planets: &Vec<types::Planet>, r: f32) -> Vec<f32> {
|
||||
planets.iter().fold(Vec::new(), |mut cum, p| {
|
||||
cum.push(p.x);
|
||||
cum.push(p.y);
|
||||
cum.push(r);
|
||||
cum
|
||||
})
|
||||
}
|
114
web/pw-frontend/public/assets/images/earth.svg
Normal file
After Width: | Height: | Size: 7.4 KiB |
118
web/pw-frontend/public/assets/images/jupiter.svg
Normal file
|
@ -0,0 +1,118 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 493.0475 493.16002"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="jupiter-with-satellite.svg"
|
||||
width="493.04749"
|
||||
height="493.16"
|
||||
inkscape:version="0.92.1 r15371"><metadata
|
||||
id="metadata45"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs43" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1536"
|
||||
inkscape:window-height="801"
|
||||
id="namedview41"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.38562218"
|
||||
inkscape:cx="-121.54471"
|
||||
inkscape:cy="246.58001"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g8" />
|
||||
<g
|
||||
id="g8"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
<path
|
||||
d="M 539.776,131.64 C 493.205,85.067 431.282,59.419 365.417,59.419 c -65.865,0 -127.785,25.649 -174.359,72.221 -96.142,96.142 -96.142,252.575 0,348.718 46.573,46.573 108.494,72.221 174.359,72.221 65.865,0 127.786,-25.648 174.359,-72.221 46.574,-46.573 72.223,-108.494 72.223,-174.359 0,-65.865 -25.647,-127.786 -72.223,-174.359 z M 375.169,405.983 c -12.849,11.452 -28.27,18.565 -40.247,18.565 -3.901,0 -9.259,-0.794 -12.626,-4.57 -3.823,-4.287 -4.311,-11.821 -1.337,-20.669 3.484,-10.375 11.047,-21.12 21.292,-30.252 12.849,-11.452 28.27,-18.565 40.247,-18.565 3.901,0 9.259,0.794 12.626,4.568 9.699,10.882 -2.733,35.57 -19.955,50.923 z m -59.521,27.38 c 5.126,3.72 11.674,5.68 19.274,5.68 15.617,0 34.268,-8.313 49.89,-22.24 23.566,-21.006 33.496,-48.135 25.096,-65.431 0.069,-0.069 0.138,-0.134 0.205,-0.203 l 0.245,-0.245 c 56.354,-56.355 104.89,-119.767 140.932,-183.964 9.652,12.849 17.879,26.565 24.597,40.957 -35.262,61.327 -80.521,119.83 -134.614,173.92 -54.098,54.099 -112.607,99.362 -173.935,134.623 -14.394,-6.719 -28.111,-14.945 -40.961,-24.599 30.178,-16.937 60.136,-36.571 89.271,-58.498 z M 466.754,97.09 c -35.38,61.735 -80.828,120.58 -135.241,174.991 -54.389,54.389 -113.209,99.824 -174.915,135.197 -5.757,-11.897 -10.44,-24.186 -14.05,-36.725 56.493,-34.46 110.419,-77.182 160.338,-127.099 49.957,-49.957 92.703,-103.921 127.17,-160.452 12.628,3.642 24.897,8.353 36.698,14.088 z m -265.444,44.8 c 43.835,-43.835 102.116,-67.977 164.109,-67.977 7.242,0 14.43,0.342 21.555,0.995 -31.234,48.087 -68.655,94.211 -111.341,137.176 -2.821,2.839 -2.807,7.429 0.034,10.25 1.413,1.404 3.262,2.107 5.108,2.107 1.863,0 3.725,-0.714 5.142,-2.14 44.565,-44.857 84.642,-94.977 116.958,-145.384 4.187,0.676 8.346,1.459 12.472,2.359 -33.458,54.163 -74.692,105.911 -122.709,153.927 -47.981,47.981 -99.69,89.192 -153.82,122.642 -16.314,-74.713 4.517,-155.981 62.492,-213.955 z m -37.988,278.24 c 62.996,-36.051 123.004,-82.362 178.439,-137.797 55.457,-55.457 101.781,-115.487 137.837,-178.506 18.062,10.238 34.849,22.985 49.928,38.064 4.164,4.164 8.148,8.46 11.953,12.874 -35.656,64.768 -84.421,128.944 -141.318,185.854 -4.865,-3.019 -10.834,-4.622 -17.665,-4.622 -15.617,0 -34.269,8.313 -49.892,22.24 -12.097,10.783 -21.113,23.731 -25.389,36.457 -3.457,10.294 -3.575,19.665 -0.495,27.248 -30.198,22.709 -61.277,42.902 -92.54,60.113 -4.414,-3.803 -8.708,-7.786 -12.872,-11.95 -15.228,-15.229 -27.882,-32.071 -37.986,-49.975 z m 366.205,49.976 c -43.835,43.835 -102.116,67.977 -164.109,67.977 -15.161,0 -30.098,-1.453 -44.659,-4.276 18.864,-11.87 37.661,-24.833 55.998,-38.625 3.2,-2.406 3.841,-6.951 1.435,-10.149 -2.406,-3.2 -6.952,-3.84 -10.149,-1.435 -19.855,14.934 -46.393,32.45 -67.363,45.368 -5.606,-1.62 -11.142,-3.448 -16.596,-5.487 58.968,-35.049 115.237,-79.19 167.435,-131.388 52.192,-52.19 96.333,-108.454 131.381,-167.423 2.049,5.485 3.887,11.051 5.512,16.69 -23.941,38.799 -55.866,83.002 -87.51,118.944 -2.645,3.004 -2.356,7.585 0.649,10.228 1.379,1.212 3.086,1.808 4.787,1.808 2.009,0 4.012,-0.832 5.443,-2.459 30.673,-34.837 58.031,-71.308 81.446,-108.536 2.821,14.559 4.276,29.493 4.276,44.652 10e-4,61.995 -24.139,120.276 -67.976,164.111 z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0" />
|
||||
|
||||
<path
|
||||
d="m 337.815,406.147 c -4.829,-5.418 0.615,-18.151 12.159,-28.441 11.544,-10.29 24.817,-14.24 29.646,-8.822 4.829,5.417 -0.615,18.151 -12.159,28.441 -11.545,10.29 -24.817,14.24 -29.646,8.822 z"
|
||||
id="path6"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
id="g10"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g12"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g14"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g16"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g18"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g20"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g22"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g24"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g26"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g28"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g30"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g32"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g34"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g36"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g38"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.9 KiB |
114
web/pw-frontend/public/assets/images/mars.svg
Normal file
|
@ -0,0 +1,114 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 272.17 272.17"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="mars-with-satellite.svg"
|
||||
width="272.17001"
|
||||
height="272.17001"
|
||||
inkscape:version="0.92.1 r15371"><metadata
|
||||
id="metadata43"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs41" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1536"
|
||||
inkscape:window-height="801"
|
||||
id="namedview39"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.74916113"
|
||||
inkscape:cx="-15.912826"
|
||||
inkscape:cy="157.50949"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g6" />
|
||||
<g
|
||||
id="g6"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
<path
|
||||
d="m 150.663,42.849 c -75.037,0 -136.085,61.047 -136.085,136.085 0,75.038 61.048,136.085 136.085,136.085 75.037,0 136.085,-61.048 136.085,-136.085 0,-75.037 -61.048,-136.085 -136.085,-136.085 z m 94.519,49.737 C 215.47,98.072 194.155,95.67 181.775,85.417 166.119,72.442 142.824,62.802 112.41,56.684 c 12.085,-3.79 24.935,-5.835 38.253,-5.835 37.388,0 71.082,16.104 94.519,41.737 z M 49.864,99.992 c 7.659,4.116 14.848,7.336 20.496,9.16 l 1.405,0.455 c 11.474,3.718 26.173,8.48 38.353,8.48 9.974,0 18.259,-3.194 21.701,-12.769 1.564,-4.354 1.492,-8.272 -0.214,-11.644 -3.639,-7.188 -13.464,-10.107 -25.902,-13.801 -2.913,-0.865 -5.924,-1.76 -8.986,-2.75 -4.31,-1.395 -10.33,-3.021 -17.181,-4.657 5.813,-3.896 11.958,-7.332 18.388,-10.249 35.034,5.547 62.249,15.687 78.747,29.361 9.52,7.883 23.149,11.833 40.721,11.833 9.978,0 21.246,-1.291 33.734,-3.842 3.017,3.811 5.819,7.799 8.394,11.942 -7.815,0.09 -15.483,0.207 -23.256,0.357 -32.772,0.63 -51.646,9.594 -69.899,18.262 -16.304,7.742 -31.704,15.056 -56.158,15.056 -19.363,0 -45.543,-6.853 -75.875,-19.812 4.196,-9.082 9.42,-17.595 15.532,-25.382 z M 71.002,78.711 c 9.393,2.083 17.789,4.256 23.251,6.023 3.154,1.021 6.213,1.929 9.171,2.808 9.751,2.896 18.96,5.631 21.043,9.745 0.436,0.861 0.892,2.351 -0.177,5.326 -4.637,12.897 -27.272,6.767 -50.06,-0.616 L 72.82,101.54 C 67.967,99.972 61.794,97.234 55.123,93.723 59.98,88.283 65.292,83.259 71.002,78.711 Z M 23.02,168.333 c 35.942,5.647 57.003,15.954 59.452,29.178 0.284,1.535 -0.071,2.922 -1.119,4.364 -2.927,4.03 -13.653,11.492 -52.407,16.946 -4.126,-12.559 -6.367,-25.966 -6.367,-39.887 -0.001,-3.57 0.153,-7.104 0.441,-10.601 z m 23.365,84.896 c 22.439,-3.993 52.181,-14.162 77.357,-39.338 42.857,-42.857 53.898,-42.857 78.089,-42.857 9.532,0 21.889,5.026 34.971,10.348 13.57,5.52 27.555,11.194 41.059,12.592 -0.781,6.647 -2.069,13.141 -3.832,19.44 -9.441,0.149 -18.893,-1.263 -28.848,-2.765 -23.035,-3.475 -49.144,-7.414 -80.863,8.749 -36.661,18.676 -56.554,50.852 -67.026,75.957 -20.42,-9.398 -37.963,-24.01 -50.907,-42.126 z m 68.931,48.827 c -3.62,-1.041 -7.173,-2.242 -10.656,-3.586 9.935,-23.833 28.755,-54.35 63.288,-71.943 29.436,-14.998 53.129,-11.422 76.039,-7.966 9.394,1.417 18.359,2.748 27.51,2.855 -2.915,8.266 -6.65,16.149 -11.117,23.543 -29.036,-6.441 -59.028,-1.667 -89.203,14.214 -24.231,12.752 -43.497,30.024 -55.861,42.883 z m 35.347,4.963 c -9.027,0 -17.837,-0.944 -26.341,-2.729 11.947,-11.958 29.304,-26.84 50.581,-38.037 27.413,-14.427 54.562,-19.154 80.787,-14.093 -23.175,33.139 -61.609,54.859 -105.027,54.859 z M 278.55,186.003 c -12.347,-1.311 -25.739,-6.745 -38.734,-12.031 -13.827,-5.625 -26.889,-10.938 -37.985,-10.938 -27.418,0 -40.278,1.733 -83.745,45.2 -25.043,25.043 -54.972,34.354 -76.548,37.691 -3.79,-6.151 -7.074,-12.644 -9.795,-19.422 31.269,-4.529 49.643,-11.06 56.083,-19.926 2.324,-3.201 3.193,-6.839 2.513,-10.521 -3.943,-21.297 -37.42,-31.136 -66.412,-35.676 1.399,-9.598 3.865,-18.853 7.275,-27.643 31.702,13.558 58.277,20.448 79.003,20.448 26.258,0 42.448,-7.689 59.59,-15.83 17.488,-8.305 35.571,-16.893 66.622,-17.49 9.222,-0.177 18.305,-0.308 27.659,-0.402 9.362,17.782 14.672,38.016 14.672,59.47 0,2.373 -0.07,4.729 -0.198,7.07 z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0" />
|
||||
|
||||
</g>
|
||||
<g
|
||||
id="g8"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g10"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g12"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g14"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g16"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g18"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g20"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g22"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g24"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g26"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g28"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g30"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g32"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g34"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g36"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.6 KiB |
186
web/pw-frontend/public/assets/images/neptune.svg
Normal file
|
@ -0,0 +1,186 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 272.044 272.17001"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="neptune-with-satellite.svg"
|
||||
width="272.04401"
|
||||
height="272.17001"
|
||||
inkscape:version="0.92.1 r15371"><metadata
|
||||
id="metadata79"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs77" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1536"
|
||||
inkscape:window-height="801"
|
||||
id="namedview75"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.75655574"
|
||||
inkscape:cx="-13.59678"
|
||||
inkscape:cy="155.969"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g42" />
|
||||
<g
|
||||
id="g42"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
<path
|
||||
d="m 148.297,39.769 c -36.35,0 -70.524,14.155 -96.227,39.858 -53.06,53.06 -53.06,139.394 0,192.454 25.703,25.703 59.877,39.858 96.227,39.858 36.35,0 70.524,-14.155 96.227,-39.858 53.06,-53.06 53.06,-139.394 0,-192.454 C 218.821,53.924 184.647,39.769 148.297,39.769 Z M 271.474,165.86 c -8.235,-5.915 -18.998,-2.783 -29.532,8.588 -8.691,9.382 -15.31,21.945 -19.67,37.341 -0.602,2.125 0.633,4.336 2.759,4.938 2.127,0.601 4.336,-0.634 4.938,-2.759 4.013,-14.169 10.016,-25.637 17.842,-34.084 3.54,-3.822 12.475,-12.208 18.997,-7.527 8.074,5.799 7.154,21.44 6.385,27.895 -1.709,14.318 -7.573,26.757 -15.687,33.274 -2.358,1.895 -5.645,3.751 -7.902,1.84 -2.635,-2.23 -3.822,-7.371 -3.344,-14.476 0.148,-2.204 -1.519,-4.111 -3.723,-4.26 -2.226,-0.138 -4.111,1.519 -4.26,3.723 -0.672,9.986 1.399,17.091 6.158,21.119 2.164,1.832 4.646,2.741 7.302,2.741 1.832,0 3.748,-0.447 5.699,-1.306 -5.142,8.369 -11.327,16.273 -18.569,23.516 -1.59,1.59 -3.216,3.13 -4.873,4.625 -3.667,-4.799 -6.198,-12.047 -7.225,-20.88 -0.256,-2.194 -2.241,-3.763 -4.437,-3.511 -2.194,0.255 -3.766,2.241 -3.511,4.436 1.23,10.565 4.34,19.14 9.059,25.132 -16.61,13.223 -36.039,21.995 -56.813,25.702 5.189,-6.479 10.531,-16.472 12.156,-31.099 0.244,-2.196 -1.338,-4.173 -3.534,-4.417 -2.186,-0.244 -4.173,1.338 -4.417,3.534 -2.288,20.594 -12.727,30.327 -17.241,33.631 -3.223,0.241 -6.469,0.364 -9.735,0.364 -34.213,0 -66.378,-13.323 -90.57,-37.516 -33.004,-33.004 -44.189,-79.685 -33.57,-121.967 11.195,1.303 26.82,4.299 43.035,11.16 0.509,0.215 1.037,0.317 1.557,0.317 1.559,0 3.04,-0.917 3.686,-2.442 0.861,-2.034 -0.09,-4.381 -2.125,-5.242 C 53.868,141.293 38.021,138.111 26.373,136.664 32.383,117.86 42.832,100.179 57.727,85.285 68.941,74.071 81.87,65.197 95.92,58.898 c -0.781,0.832 -1.538,1.704 -2.252,2.627 -5.132,6.638 -6.665,13.818 -4.432,20.764 0.676,2.103 2.932,3.261 5.032,2.584 2.104,-0.676 3.26,-2.929 2.584,-5.032 -3.119,-9.701 6.766,-18.895 16.179,-23.821 8.789,-4.599 19.379,-7.341 31.542,-8.193 1.239,-0.035 2.48,-0.058 3.724,-0.058 12.251,0 24.237,1.717 35.691,5.022 2.36,0.884 4.63,1.872 6.793,2.972 5.949,3.025 9.001,6.12 9.604,9.737 0.85,5.096 -4.18,9.225 -6.381,10.763 -11.526,8.055 -26.655,7.89 -37.317,6.332 -2.189,-0.324 -4.217,1.194 -4.536,3.38 -0.319,2.186 1.194,4.217 3.38,4.536 3.699,0.54 7.881,0.924 12.299,0.924 10.028,0 21.264,-1.981 30.757,-8.614 7.284,-5.089 10.815,-11.882 9.689,-18.635 -0.103,-0.615 -0.243,-1.208 -0.409,-1.783 8.589,4.523 16.694,10.047 24.165,16.52 -8.145,14.582 -23.589,20.575 -35.122,23.032 -2.16,0.46 -3.538,2.585 -3.078,4.746 0.4,1.88 2.061,3.167 3.908,3.167 0.276,0 0.557,-0.029 0.838,-0.089 12.722,-2.711 29.678,-9.305 39.469,-25.296 0.273,0.269 0.551,0.531 0.823,0.803 23.661,23.662 36.104,54.354 37.344,85.415 -1.287,-1.834 -2.844,-3.479 -4.74,-4.841 z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 137.556,85.235 c 0.603,0.324 1.251,0.478 1.891,0.478 1.425,0 2.804,-0.764 3.526,-2.106 1.046,-1.946 0.317,-4.371 -1.628,-5.417 -1.062,-0.571 -6.264,-3.626 -4.383,-7.716 1.226,-2.667 4.829,-4.64 11.012,-6.032 6.876,-1.548 17.445,-1.943 24.605,2.034 1.188,0.66 1.884,1.448 1.862,2.11 -0.027,0.803 -0.928,2.024 -2.877,2.94 -2,0.94 -2.858,3.322 -1.919,5.322 0.94,1.999 3.322,2.859 5.321,1.918 4.54,-2.133 7.332,-5.838 7.47,-9.91 0.128,-3.778 -2.05,-7.195 -5.973,-9.374 -9.12,-5.066 -21.604,-4.792 -30.247,-2.845 -5.602,1.261 -13.409,3.721 -16.523,10.494 -3.061,6.654 0.099,13.93 7.863,18.104 z"
|
||||
id="path4"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 100.492,96.756 c 2.997,2.273 6.354,4.294 10.263,6.181 0.561,0.271 1.152,0.398 1.735,0.398 1.487,0 2.916,-0.833 3.605,-2.263 0.96,-1.99 0.125,-4.381 -1.864,-5.341 -3.424,-1.652 -6.337,-3.402 -8.906,-5.35 -1.76,-1.335 -4.27,-0.991 -5.604,0.77 -1.334,1.762 -0.989,4.271 0.771,5.605 z"
|
||||
id="path6"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 179.091,111.757 c 0.047,10e-4 4.807,-0.026 7.63,-0.253 2.202,-0.177 3.844,-2.106 3.667,-4.308 -0.177,-2.203 -2.137,-3.843 -4.308,-3.667 -4.037,0.325 -6.639,0.235 -6.68,0.233 -2.181,-0.089 -4.063,1.634 -4.149,3.84 -0.086,2.208 1.633,4.068 3.84,4.155 z"
|
||||
id="path8"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 201.867,133.619 c 0.336,0 9.337,-2.448 13.524,-3.81 2.101,-0.683 3.25,-2.94 2.566,-5.041 -0.684,-2.101 -2.938,-3.25 -5.041,-2.567 -4.04,1.314 -8.099,2.507 -12.062,3.547 -2.138,0.561 -3.415,2.748 -2.854,4.884 0.472,1.798 2.092,2.987 3.867,2.987 z"
|
||||
id="path10"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 187.617,128.737 c -46.298,8.716 -77.082,-4.029 -94.75,-16.257 -1.817,-1.257 -4.309,-0.804 -5.565,1.013 -1.257,1.816 -0.804,4.308 1.013,5.565 14.605,10.108 37.502,20.561 69.73,20.561 9.526,0 19.871,-0.914 31.054,-3.02 2.171,-0.409 3.6,-2.5 3.19,-4.671 -0.41,-2.172 -2.508,-3.602 -4.672,-3.191 z"
|
||||
id="path12"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 77.141,110.083 c 0.771,0.723 1.753,1.081 2.733,1.081 1.068,0 2.133,-0.425 2.92,-1.266 1.51,-1.612 1.427,-4.144 -0.185,-5.654 -3.733,-3.497 -5.615,-5.951 -5.675,-6.029 -1.327,-1.763 -3.831,-2.119 -5.596,-0.795 -1.768,1.326 -2.125,3.833 -0.8,5.6 0.092,0.121 2.267,3.001 6.603,7.063 z"
|
||||
id="path14"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 41.149,171.992 c -1.633,-0.278 -3.294,-0.535 -4.938,-0.763 -2.188,-0.302 -4.208,1.224 -4.512,3.411 -0.304,2.188 1.223,4.208 3.412,4.513 1.563,0.217 5.149,0.783 5.373,0.783 1.915,0 3.607,-1.379 3.938,-3.33 0.37,-2.178 -1.095,-4.244 -3.273,-4.614 z"
|
||||
id="path16"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 53.789,182.977 c 13.524,3.751 45.748,15.723 52.875,45.778 0.436,1.839 2.077,3.078 3.889,3.078 0.306,0 0.616,-0.035 0.926,-0.109 2.149,-0.51 3.479,-2.666 2.969,-4.815 -3.121,-13.162 -10.671,-24.582 -22.441,-33.944 -9.71,-7.724 -22.186,-13.843 -36.079,-17.697 -2.125,-0.589 -4.333,0.656 -4.924,2.785 -0.59,2.129 0.656,4.333 2.785,4.924 z"
|
||||
id="path18"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 110.315,242.16 c -2.004,-0.927 -4.382,-0.057 -5.311,1.948 -1.013,2.187 -2.39,4.152 -4.093,5.843 -1.568,1.557 -1.577,4.089 -0.02,5.657 0.782,0.788 1.81,1.182 2.838,1.182 1.019,0 2.039,-0.387 2.818,-1.162 2.378,-2.362 4.301,-5.106 5.715,-8.157 0.929,-2.005 0.057,-4.383 -1.947,-5.311 z"
|
||||
id="path20"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 90.255,255.468 c -8.356,1.642 -17.778,-1.182 -24.588,-7.365 -12.756,-11.582 -12.75,-24.255 -8.729,-29.174 3.817,-4.669 8.713,-5.013 12.147,-4.479 6.578,1.022 13.085,6.143 15.473,12.175 0.813,2.054 3.139,3.062 5.191,2.247 2.054,-0.813 3.06,-3.137 2.247,-5.191 -3.473,-8.774 -12.187,-15.66 -21.683,-17.136 -7.773,-1.208 -14.724,1.392 -19.57,7.321 -10.192,12.469 -0.554,30.991 9.545,40.16 6.995,6.351 16.232,9.895 25.219,9.894 2.12,0 4.228,-0.197 6.288,-0.602 2.168,-0.426 3.58,-2.528 3.155,-4.696 -0.425,-2.167 -2.526,-3.58 -4.695,-3.154 z"
|
||||
id="path22"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 82.824,236.937 c -2.256,1.781 -4.846,1.359 -6.622,0.692 -3.652,-1.372 -6.874,-4.924 -7.496,-8.263 -0.404,-2.171 -2.489,-3.603 -4.665,-3.2 -2.172,0.405 -3.604,2.493 -3.2,4.665 1.129,6.061 6.289,11.936 12.547,14.287 1.924,0.723 3.86,1.08 5.739,1.08 3.157,0 6.152,-1.008 8.651,-2.98 1.734,-1.368 2.031,-3.883 0.663,-5.618 -1.367,-1.735 -3.883,-2.032 -5.617,-0.663 z"
|
||||
id="path24"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 109.058,172.892 c -1.629,-1.493 -4.159,-1.385 -5.652,0.243 -1.494,1.628 -1.385,4.158 0.243,5.652 10.774,9.886 29.278,29.985 32.162,53.524 1.465,11.963 -1.974,23.543 -9.683,32.606 -3.238,3.808 -6.859,6.886 -10.763,9.15 -1.911,1.108 -2.562,3.556 -1.453,5.467 0.742,1.279 2.084,1.994 3.464,1.994 0.681,0 1.372,-0.174 2.003,-0.541 4.693,-2.722 9.014,-6.385 12.843,-10.887 9.176,-10.787 13.271,-24.552 11.53,-38.762 -3.196,-26.086 -23.109,-47.815 -34.694,-58.446 z"
|
||||
id="path26"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 94.011,170.834 c 0.716,0.531 1.551,0.788 2.379,0.788 1.223,0 2.431,-0.56 3.216,-1.618 1.316,-1.774 0.944,-4.28 -0.831,-5.595 -1.901,-1.41 -3.876,-2.792 -5.871,-4.108 -1.844,-1.217 -4.325,-0.708 -5.542,1.135 -1.217,1.844 -0.708,4.325 1.135,5.542 1.874,1.235 3.729,2.533 5.514,3.856 z"
|
||||
id="path28"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 151.585,173.576 c -1.26,-1.815 -3.749,-2.266 -5.564,-1.009 -1.815,1.257 -2.268,3.749 -1.012,5.564 0.312,0.451 30.974,45.477 13.988,80.185 -0.971,1.984 -0.149,4.38 1.835,5.351 0.565,0.277 1.165,0.408 1.755,0.408 1.479,0 2.901,-0.824 3.596,-2.243 7.945,-16.236 7.9,-36.706 -0.13,-59.195 -5.964,-16.7 -14.125,-28.565 -14.468,-29.061 z"
|
||||
id="path30"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 257.729,197.605 c 2.204,-1.072 3.393,3.135 3.063,8.028 -0.148,2.204 1.518,4.112 3.722,4.26 0.092,0.006 0.183,0.009 0.273,0.009 2.086,0 3.845,-1.618 3.987,-3.73 0.482,-7.146 -1.438,-12.739 -5.267,-15.344 -2.692,-1.832 -5.965,-1.991 -9.21,-0.45 -1.996,0.948 -2.845,3.334 -1.897,5.33 0.948,1.996 3.344,2.863 5.329,1.897 z"
|
||||
id="path32"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 219.052,227.503 c -0.246,1.928 -0.436,3.879 -0.563,5.801 -0.147,2.204 1.521,4.11 3.725,4.257 0.091,0.006 0.181,0.009 0.271,0.009 2.088,0 3.846,-1.62 3.987,-3.734 0.117,-1.762 0.291,-3.552 0.517,-5.322 0.279,-2.191 -1.271,-4.194 -3.463,-4.473 -2.187,-0.282 -4.195,1.272 -4.474,3.462 z"
|
||||
id="path34"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 215.557,170.546 c -1.205,1.852 -0.681,4.33 1.171,5.535 0.674,0.438 1.43,0.647 2.178,0.647 1.309,0 2.59,-0.641 3.356,-1.819 11.387,-17.501 23.308,-27.803 36.441,-31.495 2.127,-0.598 3.366,-2.806 2.769,-4.933 -0.598,-2.126 -2.809,-3.368 -4.933,-2.768 -15.084,4.24 -28.491,15.634 -40.982,34.833 z"
|
||||
id="path36"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 206.98,213.368 c 0.409,-2.171 -1.019,-4.263 -3.189,-4.672 -2.163,-0.412 -4.263,1.018 -4.672,3.189 -6.977,36.974 4.454,68.118 4.943,69.425 0.603,1.606 2.126,2.596 3.745,2.596 0.466,0 0.939,-0.082 1.4,-0.254 2.068,-0.773 3.118,-3.077 2.348,-5.146 -0.112,-0.3 -11.122,-30.441 -4.575,-65.138 z"
|
||||
id="path38"
|
||||
inkscape:connector-curvature="0" />
|
||||
|
||||
</g>
|
||||
<g
|
||||
id="g44"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g46"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g48"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g50"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g52"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g54"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g56"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g58"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g60"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g62"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g64"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g66"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g68"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g70"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g72"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 12 KiB |
79
web/pw-frontend/public/assets/images/rocket.svg
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 265.423 265.423" width="265.423" height="265.423" style="enable-background:new 0 0 265.423 265.423;" xml:space="preserve">
|
||||
<g>
|
||||
<path d="M178.689,144.714c52.71-52.71,86.132-138.415,86.463-139.274c0.569-1.477,0.215-3.149-0.903-4.268
|
||||
s-2.792-1.473-4.268-0.904c-0.86,0.332-86.565,33.754-139.275,86.464c-8.581,8.581-15.959,16.57-22.168,24.013l-10.158-2.289
|
||||
c7.048-17.806,10.429-32.508,10.662-33.541c0.348-1.543-0.245-3.146-1.515-4.091c-1.27-0.942-2.976-1.051-4.354-0.273
|
||||
c-1.579,0.892-38.902,22.154-60.387,51.041c-11.011,14.805-16.817,26.156-17.75,34.704c-0.154,1.41,0.451,2.797,1.589,3.644
|
||||
l18.829,14.003c0.702,0.521,1.541,0.79,2.388,0.79c0.527,0,1.058-0.104,1.559-0.316c6.105-2.584,12.977-8.438,20.85-17.764
|
||||
l12.899,2.908c-0.044,0.909-0.057,1.807-0.027,2.69l-14.11,14.11c-1.562,1.562-1.562,4.095,0,5.656l24.395,24.396
|
||||
c0.781,0.781,1.805,1.172,2.829,1.172c1.023,0,2.047-0.391,2.829-1.172l14.12-14.119c0.362,0.012,0.724,0.025,1.091,0.025
|
||||
c0.522,0,1.05-0.016,1.581-0.041l2.91,12.893c-9.325,7.873-15.179,14.745-17.762,20.849c-0.553,1.307-0.373,2.809,0.474,3.946
|
||||
l14.003,18.828c0.759,1.021,1.953,1.613,3.209,1.613c0.144,0,0.289-0.008,0.434-0.023c8.547-0.933,19.898-6.738,34.704-17.749
|
||||
c28.887-21.485,50.15-58.809,51.042-60.387c0.778-1.378,0.67-3.085-0.274-4.354c-0.945-1.27-2.55-1.865-4.091-1.515
|
||||
c-1.032,0.232-15.736,3.614-33.544,10.663l-2.286-10.138C162.105,160.693,170.084,153.318,178.689,144.714z M220.677,76.274
|
||||
c-12.517-8.22-23.307-19.01-31.527-31.527c26.944-16.301,52.071-27.837,64.873-33.348
|
||||
C248.515,24.199,236.982,49.325,220.677,76.274z M126.363,92.387c16.565-16.565,36.509-31.196,55.974-43.438
|
||||
c8.876,13.571,20.565,25.261,34.137,34.138c-12.24,19.459-26.872,39.4-43.443,55.971c-30.455,30.455-52.945,45.26-68.755,45.26
|
||||
c-6.154,0-11.269-2.249-16.097-7.076c-7.308-7.308-8.891-15.574-5.132-26.806C87.963,135.744,102.536,116.215,126.363,92.387z
|
||||
M38.273,166.066l-14.916-11.093c1.527-6.898,6.847-16.506,15.849-28.609c14.469-19.453,37.249-35.72,49.478-43.65
|
||||
c-4.078,13.993-13.103,40.49-27.571,59.944C52.11,154.762,44.44,162.62,38.273,166.066z M65.815,149.704
|
||||
c0.568-0.744,1.138-1.495,1.716-2.272c7.214-9.7,13.09-20.861,17.73-31.478l7.704,1.736c-8.757,11.369-14.55,21.378-17.504,30.208
|
||||
c-0.425,1.27-0.772,2.51-1.083,3.737L65.815,149.704z M86.237,197.926l-18.738-18.738l7.511-7.511
|
||||
c1.554,4.026,4.049,7.758,7.512,11.221c3.483,3.483,7.203,5.977,11.222,7.521L86.237,197.926z M139.055,226.214
|
||||
c-12.104,9.002-21.709,14.322-28.608,15.849l-11.093-14.915c3.447-6.167,11.305-13.837,23.409-22.839
|
||||
c19.454-14.47,45.951-23.494,59.944-27.571C174.775,188.965,158.509,211.745,139.055,226.214z M149.465,180.16
|
||||
c-10.616,4.64-21.778,10.515-31.477,17.729c-0.778,0.579-1.53,1.149-2.275,1.718l-1.928-8.543
|
||||
c9.786-2.453,20.97-8.558,33.95-18.573L149.465,180.16z"/>
|
||||
<path d="M172.264,113.241c5.209,0,10.105-2.028,13.789-5.712c3.684-3.683,5.712-8.579,5.712-13.788s-2.028-10.105-5.711-13.788
|
||||
c-3.683-3.684-8.58-5.712-13.789-5.712c-5.208,0-10.105,2.028-13.788,5.712c-3.684,3.683-5.712,8.579-5.712,13.788
|
||||
s2.028,10.105,5.712,13.788C162.159,111.213,167.055,113.241,172.264,113.241z M164.132,85.609c2.172-2.172,5.06-3.368,8.131-3.368
|
||||
c3.072,0,5.96,1.196,8.132,3.368c2.172,2.172,3.368,5.061,3.368,8.132s-1.196,5.96-3.368,8.132
|
||||
c-2.172,2.172-5.06,3.368-8.132,3.368c-3.072,0-5.959-1.196-8.132-3.368c-2.172-2.172-3.368-5.061-3.368-8.132
|
||||
S161.96,87.781,164.132,85.609z"/>
|
||||
<path d="M35.502,194.423c-19.575,0-35.5,15.925-35.5,35.5v31.5c0,2.209,1.791,4,4,4h31.5c19.575,0,35.5-15.925,35.5-35.5
|
||||
S55.077,194.423,35.502,194.423z M46.16,207.12c6.697,0,12.145,5.448,12.145,12.146c0,6.696-5.448,12.145-12.145,12.145H34.015
|
||||
v-12.145C34.015,212.568,39.463,207.12,46.16,207.12z M35.502,257.423h-27.5v-27.5c0-15.036,12.132-27.285,27.12-27.49
|
||||
c-5.478,3.604-9.108,9.799-9.108,16.833v16.145c0,2.209,1.791,4,4,4H46.16c7.034,0,13.229-3.63,16.833-9.108
|
||||
C62.788,245.29,50.539,257.423,35.502,257.423z"/>
|
||||
<path d="M215.69,68.984c0.702,0.497,1.509,0.735,2.309,0.735c1.253,0,2.488-0.588,3.268-1.688
|
||||
c2.309-3.259,6.74-11.083,13.172-23.255c1.032-1.953,0.285-4.374-1.668-5.405c-1.952-1.033-4.373-0.285-5.405,1.667
|
||||
c-7.81,14.78-11.178,20.323-12.627,22.37C213.461,65.211,213.887,67.707,215.69,68.984z"/>
|
||||
<path d="M234.237,36.556c0.588,0.304,1.215,0.448,1.834,0.448c1.448,0,2.846-0.789,3.557-2.164
|
||||
c2.243-4.338,3.743-7.294,3.743-7.294c1-1.971,0.213-4.378-1.757-5.378c-1.969-0.997-4.377-0.213-5.377,1.757
|
||||
c-0.003,0.007-1.492,2.939-3.716,7.241C231.507,33.129,232.275,35.542,234.237,36.556z"/>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.9 KiB |
150
web/pw-frontend/public/assets/images/uranus.svg
Normal file
|
@ -0,0 +1,150 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 272.04324 272.17001"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="uranus-with-satellite.svg"
|
||||
inkscape:version="0.92.1 r15371"
|
||||
width="272.04324"
|
||||
height="272.17001"><metadata
|
||||
id="metadata61"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs59" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1536"
|
||||
inkscape:window-height="801"
|
||||
id="namedview57"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.69664401"
|
||||
inkscape:cx="-68.159453"
|
||||
inkscape:cy="136.0855"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Capa_1" />
|
||||
<g
|
||||
id="g24"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
<path
|
||||
d="M 298.973,73.157 C 273.271,47.454 239.096,33.299 202.746,33.299 c -36.35,0 -70.523,14.155 -96.227,39.858 -53.06,53.06 -53.06,139.394 0,192.454 25.703,25.703 59.877,39.858 96.227,39.858 36.35,0 70.524,-14.155 96.227,-39.858 53.059,-53.061 53.059,-139.395 0,-192.454 z m -5.657,186.796 c -11.681,11.681 -25.225,20.819 -39.956,27.156 17.744,-11.698 34.215,-26.208 48.558,-42.92 1.438,-1.676 1.246,-4.202 -0.43,-5.64 -1.678,-1.44 -4.202,-1.247 -5.641,0.43 -20.23,23.57 -48.084,44.664 -75.601,57.302 -5.753,0.781 -11.595,1.188 -17.501,1.188 -4.154,0 -8.276,-0.2 -12.359,-0.589 17.939,-6.343 34.995,-14.887 50.872,-25.52 1.836,-1.229 2.327,-3.714 1.098,-5.549 -1.229,-1.835 -3.712,-2.328 -5.549,-1.098 -19.625,13.143 -41.113,22.987 -63.873,29.279 -5.029,-1.193 -9.966,-2.688 -14.791,-4.477 4.071,-0.974 8.123,-2.079 12.128,-3.313 2.111,-0.651 3.296,-2.89 2.645,-5.001 -0.649,-2.11 -2.89,-3.294 -5,-2.645 -7.405,2.282 -14.973,4.095 -22.518,5.427 -11.638,-5.838 -22.419,-13.502 -31.997,-22.834 4.553,-0.896 9.091,-1.914 13.555,-3.076 2.138,-0.556 3.421,-2.74 2.864,-4.878 -0.555,-2.138 -2.736,-3.42 -4.878,-2.864 -5.959,1.55 -12.05,2.85 -18.137,3.902 C 96.417,242.502 88.55,229.31 83.208,215.361 c 7.844,-2.009 15.644,-4.451 23.246,-7.289 2.069,-0.772 3.121,-3.077 2.348,-5.146 -0.772,-2.069 -3.079,-3.122 -5.146,-2.348 -7.545,2.817 -15.292,5.233 -23.078,7.202 -1.7,-5.44 -3.033,-10.971 -3.992,-16.555 17.341,-5.604 33.99,-13.242 49.518,-22.786 1.882,-1.157 2.47,-3.62 1.313,-5.502 -1.158,-1.881 -3.62,-2.47 -5.503,-1.313 -14.584,8.964 -30.193,16.189 -46.445,21.555 -0.793,-7.386 -0.95,-14.826 -0.465,-22.234 8.314,-3.591 16.365,-7.688 23.955,-12.209 1.897,-1.13 2.521,-3.585 1.39,-5.483 -1.13,-1.898 -3.585,-2.521 -5.483,-1.39 -6.041,3.597 -12.387,6.918 -18.932,9.917 1.118,-8.127 3.015,-16.165 5.69,-23.995 12.924,-7.601 26.339,-17.69 37.186,-27.603 1.631,-1.49 1.745,-4.02 0.255,-5.651 -1.491,-1.632 -4.021,-1.745 -5.651,-0.254 -8.4,7.676 -17.365,14.679 -26.729,20.916 6.137,-13.178 14.632,-25.519 25.492,-36.379 24.192,-24.192 56.357,-37.516 90.57,-37.516 4.656,0 9.271,0.255 13.836,0.743 -1.347,4.072 -2.817,8.13 -4.393,12.113 -0.813,2.054 0.193,4.378 2.248,5.191 0.482,0.191 0.98,0.282 1.471,0.282 1.593,0 3.099,-0.958 3.721,-2.529 1.813,-4.582 3.485,-9.26 5.002,-13.947 5.613,0.961 11.128,2.297 16.52,3.984 -6.004,23.81 -15.831,46.266 -29.255,66.792 -1.209,1.849 -0.69,4.328 1.158,5.537 0.676,0.442 1.435,0.653 2.186,0.653 1.305,0 2.584,-0.638 3.352,-1.811 13.785,-21.077 23.913,-44.115 30.148,-68.536 14.147,5.434 27.287,13.409 38.866,23.679 -2.015,11.874 -5.07,23.73 -9.118,35.272 -0.731,2.084 0.365,4.367 2.45,5.099 0.438,0.154 0.885,0.227 1.324,0.227 1.651,0 3.197,-1.03 3.774,-2.677 3.599,-10.259 6.438,-20.76 8.495,-31.309 16.699,17.153 27.627,37.862 32.781,59.675 -6.798,23.85 -17.03,45.879 -30.438,65.486 -1.247,1.823 -0.779,4.313 1.044,5.56 0.69,0.472 1.477,0.699 2.254,0.699 1.276,0 2.531,-0.61 3.306,-1.743 11.018,-16.112 19.958,-33.794 26.699,-52.727 3.538,36.789 -8.748,74.828 -36.862,102.942 z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0" />
|
||||
|
||||
<path
|
||||
d="m 197.27,216.666 c -1.811,1.267 -2.251,3.761 -0.984,5.571 0.778,1.112 2.02,1.707 3.281,1.707 0.791,0 1.592,-0.235 2.289,-0.723 22.879,-16.008 42.555,-36.287 58.479,-60.273 4.438,-6.686 8.573,-13.669 12.288,-20.754 1.025,-1.957 0.271,-4.375 -1.686,-5.4 -1.952,-1.025 -4.374,-0.272 -5.4,1.685 -3.587,6.843 -7.58,13.587 -11.866,20.044 -15.37,23.149 -34.347,42.711 -56.401,58.143 z"
|
||||
id="path6"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 164.66,235.919 c -4.826,2.292 -9.791,4.417 -14.757,6.314 -2.063,0.789 -3.098,3.101 -2.309,5.164 0.609,1.594 2.127,2.573 3.737,2.573 0.475,0 0.957,-0.085 1.427,-0.265 5.16,-1.972 10.319,-4.179 15.333,-6.561 1.996,-0.948 2.845,-3.334 1.897,-5.329 -0.946,-1.994 -3.333,-2.842 -5.328,-1.896 z"
|
||||
id="path8"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 240.418,146.561 c 1.275,-1.804 0.846,-4.3 -0.958,-5.575 -1.803,-1.275 -4.3,-0.845 -5.575,0.958 -30.046,42.51 -72.305,73.713 -118.993,87.863 -2.114,0.641 -3.309,2.874 -2.668,4.988 0.523,1.728 2.11,2.841 3.826,2.841 0.385,0 0.775,-0.056 1.162,-0.173 48.383,-14.663 92.138,-46.946 123.206,-90.902 z"
|
||||
id="path10"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 131.021,125.104 c 22.662,-18.894 41.814,-42.449 55.387,-68.119 1.032,-1.953 0.286,-4.373 -1.667,-5.406 -1.954,-1.035 -4.373,-0.286 -5.405,1.667 -13.09,24.758 -31.568,47.481 -53.438,65.714 -1.696,1.415 -1.926,3.937 -0.511,5.634 0.791,0.949 1.929,1.438 3.074,1.438 0.903,0 1.811,-0.304 2.56,-0.928 z"
|
||||
id="path12"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 304.583,162.73 c 0.537,0.244 1.1,0.359 1.653,0.359 1.52,0 2.974,-0.872 3.644,-2.346 0.838,-1.843 1.658,-3.714 2.44,-5.563 0.861,-2.034 -0.091,-4.381 -2.125,-5.242 -2.035,-0.861 -4.382,0.09 -5.242,2.125 -0.755,1.784 -1.548,3.59 -2.356,5.37 -0.914,2.012 -0.025,4.383 1.986,5.297 z"
|
||||
id="path14"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 301.081,169.845 c -1.931,-1.072 -4.365,-0.374 -5.438,1.557 -5.468,9.855 -11.719,19.443 -18.58,28.495 -25.229,33.293 -57.633,58.594 -93.705,73.166 -2.049,0.828 -3.038,3.159 -2.211,5.207 0.629,1.558 2.128,2.503 3.71,2.503 0.499,0 1.007,-0.094 1.497,-0.292 37.412,-15.114 70.983,-41.308 97.085,-75.752 7.089,-9.353 13.548,-19.26 19.2,-29.446 1.071,-1.932 0.374,-4.366 -1.558,-5.438 z"
|
||||
id="path16"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 190.943,141.11 c -4.038,4.545 -8.354,8.994 -12.827,13.222 -1.605,1.518 -1.678,4.049 -0.16,5.655 0.787,0.833 1.846,1.252 2.908,1.252 0.985,0 1.974,-0.362 2.746,-1.093 4.643,-4.387 9.122,-9.004 13.313,-13.723 1.468,-1.652 1.318,-4.18 -0.334,-5.647 -1.651,-1.466 -4.179,-1.318 -5.646,0.334 z"
|
||||
id="path18"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 161.323,130.713 c -1.609,1.514 -1.688,4.045 -0.174,5.654 0.787,0.837 1.85,1.26 2.915,1.26 0.982,0 1.967,-0.36 2.739,-1.086 18.801,-17.681 32.125,-35.242 40.733,-53.688 0.934,-2.001 0.068,-4.382 -1.934,-5.316 -2.001,-0.934 -4.382,-0.069 -5.316,1.933 -8.17,17.509 -20.915,34.271 -38.963,51.243 z"
|
||||
id="path20"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 148.218,142.343 c -3.322,2.801 -6.804,5.649 -10.644,8.706 -1.729,1.376 -2.014,3.893 -0.638,5.621 0.789,0.992 1.955,1.508 3.132,1.508 0.873,0 1.752,-0.285 2.488,-0.871 3.899,-3.104 7.438,-5.999 10.817,-8.849 1.689,-1.424 1.904,-3.948 0.479,-5.637 -1.422,-1.687 -3.947,-1.902 -5.634,-0.478 z"
|
||||
id="path22"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
id="g26"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g28"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g30"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g32"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g34"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g36"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g38"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g40"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g42"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g44"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g46"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g48"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g50"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g52"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g54"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 8.8 KiB |
114
web/pw-frontend/public/assets/images/venus.svg
Normal file
|
@ -0,0 +1,114 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 272.17001 272.17001"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="venus-with-satellite.svg"
|
||||
width="272.17001"
|
||||
height="272.17001"
|
||||
inkscape:version="0.92.1 r15371"><metadata
|
||||
id="metadata43"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs41" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1536"
|
||||
inkscape:window-height="801"
|
||||
id="namedview39"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.72525674"
|
||||
inkscape:cx="-54.610822"
|
||||
inkscape:cy="136.085"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g6" />
|
||||
<g
|
||||
id="g6"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
<path
|
||||
d="m 189.317,26.616 c -75.038,0 -136.085,61.048 -136.085,136.085 0,75.037 61.047,136.085 136.085,136.085 75.038,0 136.085,-61.047 136.085,-136.085 0,-75.038 -61.048,-136.085 -136.085,-136.085 z m 114.537,78.799 c -19.285,81.007 -76.736,147.79 -154.087,179.114 -5.259,-1.711 -10.371,-3.751 -15.309,-6.102 80.857,-31.451 141.937,-101.332 162.187,-185.549 2.629,4.029 5.038,8.214 7.209,12.537 z M 163.18,139.149 c 26.371,-28.772 46.301,-63.476 57.841,-100.56 13.174,3.367 25.536,8.784 36.729,15.887 -19.382,87.483 -83.595,159.155 -168.504,188.074 -8.839,-11.054 -15.885,-23.598 -20.7,-37.19 35.734,-14.765 68.396,-37.583 94.634,-66.211 z M 66.097,197.717 C 64.659,192.664 63.525,187.485 62.714,182.201 125,152.771 174.179,99.363 198.318,34.937 c 5.041,0.352 10.001,0.997 14.865,1.918 -11.221,35.723 -30.474,69.147 -55.901,96.888 -25.304,27.609 -56.763,49.647 -91.185,63.974 z M 189.317,34.616 c 0.192,0 0.382,0.006 0.573,0.007 -23.415,60.543 -69.7,110.809 -128.17,139.196 -0.317,-3.665 -0.488,-7.372 -0.488,-11.118 0,-70.626 57.458,-128.085 128.085,-128.085 z M 94.827,249.08 c 85.048,-30.115 149.458,-102 170.022,-189.755 9.626,7.052 18.236,15.411 25.562,24.818 -18.383,87.024 -81.532,159.278 -165.428,189.276 -11.251,-6.562 -21.416,-14.787 -30.156,-24.339 z m 67.417,38.818 c 71.824,-32.367 125.65,-94.933 146.817,-170.653 4.421,11.608 7.2,24.017 8.052,36.946 -20.52,57.053 -60.724,105.217 -113.336,135.774 -4.748,0.536 -9.571,0.821 -14.46,0.821 -9.287,0 -18.342,-1.002 -27.073,-2.888 z m 63.449,-2.382 c 39.622,-27.44 71.097,-65.121 90.95,-108.895 -5.626,51.82 -42.283,94.456 -90.95,108.895 z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0" />
|
||||
|
||||
</g>
|
||||
<g
|
||||
id="g8"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g10"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g12"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g14"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g16"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g18"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g20"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g22"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g24"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g26"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g28"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g30"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g32"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g34"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g36"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.1 KiB |
BIN
web/pw-frontend/public/favicon.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
43
web/pw-frontend/public/match.log
Normal file
|
@ -0,0 +1,43 @@
|
|||
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":0,"ship_count":5,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":1,"ship_count":5,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":11}]}
|
||||
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":0,"ship_count":5,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":1,"ship_count":5,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":10},{"id":2,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":11},{"id":3,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":11}]}
|
||||
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":0,"ship_count":5,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":1,"ship_count":5,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":9},{"id":2,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":10},{"id":3,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":10},{"id":4,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":11},{"id":5,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":11}]}
|
||||
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":0,"ship_count":5,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":1,"ship_count":5,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":8},{"id":2,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":9},{"id":3,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":9},{"id":4,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":10},{"id":5,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":10},{"id":6,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":11},{"id":7,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":11}]}
|
||||
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":0,"ship_count":5,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":1,"ship_count":5,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":7},{"id":2,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":8},{"id":3,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":8},{"id":4,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":9},{"id":5,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":9},{"id":6,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":10},{"id":7,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":10},{"id":8,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":11},{"id":9,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":11}]}
|
||||
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":11},{"id":1,"ship_count":5,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":6},{"id":2,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":7},{"id":3,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":7},{"id":4,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":8},{"id":5,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":8},{"id":6,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":9},{"id":7,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":9},{"id":8,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":10},{"id":9,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":10},{"id":10,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":11}]}
|
||||
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":10},{"id":1,"ship_count":5,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":5},{"id":2,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":6},{"id":3,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":6},{"id":4,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":7},{"id":5,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":7},{"id":6,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":8},{"id":7,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":8},{"id":8,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":9},{"id":9,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":9},{"id":10,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":10},{"id":12,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":13,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":10}]}
|
||||
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":9},{"id":1,"ship_count":5,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":4},{"id":2,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":5},{"id":3,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":5},{"id":4,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":6},{"id":5,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":6},{"id":6,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":7},{"id":7,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":7},{"id":8,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":8},{"id":9,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":8},{"id":10,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":9},{"id":12,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":13,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":9},{"id":14,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":15,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":10}]}
|
||||
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":8},{"id":1,"ship_count":5,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":3},{"id":2,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":4},{"id":3,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":4},{"id":4,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":5},{"id":5,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":5},{"id":6,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":6},{"id":7,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":6},{"id":8,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":7},{"id":9,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":7},{"id":10,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":8},{"id":12,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":13,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":8},{"id":14,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":15,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":9},{"id":16,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":17,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":10}]}
|
||||
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":7},{"id":1,"ship_count":5,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":2},{"id":2,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":3},{"id":3,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":3},{"id":4,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":4},{"id":5,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":4},{"id":6,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":5},{"id":7,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":5},{"id":8,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":6},{"id":9,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":6},{"id":10,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":7},{"id":12,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":13,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":7},{"id":14,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":15,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":8},{"id":16,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":17,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":9},{"id":18,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":19,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":10}]}
|
||||
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":6},{"id":1,"ship_count":5,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":1},{"id":2,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":2},{"id":3,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":2},{"id":4,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":3},{"id":5,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":3},{"id":6,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":4},{"id":7,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":4},{"id":8,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":5},{"id":9,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":5},{"id":10,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":6},{"id":12,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":13,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":6},{"id":14,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":15,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":7},{"id":16,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":17,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":8},{"id":18,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":19,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":9},{"id":20,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":21,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":10}]}
|
||||
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":0,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":5},{"id":23,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":10},{"id":2,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":1},{"id":3,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":1},{"id":4,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":2},{"id":5,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":2},{"id":6,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":3},{"id":7,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":3},{"id":8,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":4},{"id":9,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":4},{"id":10,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":5},{"id":22,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":13,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":5},{"id":14,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":15,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":6},{"id":16,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":17,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":7},{"id":18,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":19,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":8},{"id":20,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":21,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":9}]}
|
||||
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":4},{"id":23,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":9},{"id":24,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":5},{"id":21,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":8},{"id":4,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":1},{"id":5,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":1},{"id":6,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":2},{"id":7,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":2},{"id":8,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":3},{"id":9,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":3},{"id":10,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":4},{"id":22,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":13,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":4},{"id":20,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":15,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":5},{"id":16,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":17,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":6},{"id":18,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":19,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":7}]}
|
||||
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":3},{"id":23,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":8},{"id":24,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":4},{"id":21,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":7},{"id":25,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":5},{"id":19,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":6},{"id":6,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":1},{"id":7,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":1},{"id":8,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":2},{"id":9,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":2},{"id":10,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":3},{"id":22,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":13,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":3},{"id":20,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":15,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":4},{"id":18,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":17,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":5}]}
|
||||
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":2},{"id":23,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":7},{"id":24,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":3},{"id":21,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":6},{"id":25,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":4},{"id":19,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":5},{"id":27,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":5},{"id":26,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":10},{"id":8,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":1},{"id":9,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":1},{"id":10,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":2},{"id":22,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":13,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":2},{"id":20,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":15,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":3},{"id":17,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":4}]}
|
||||
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetratos","destination":"protos","owner":2,"turns_remaining":1},{"id":23,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":6},{"id":24,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":2},{"id":21,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":5},{"id":25,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":3},{"id":19,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":4},{"id":27,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":4},{"id":26,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":9},{"id":29,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":5},{"id":28,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":10},{"id":10,"ship_count":1,"origin":"protos","destination":"tetratos","owner":1,"turns_remaining":1},{"id":22,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":13,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":1},{"id":17,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":3},{"id":15,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":2}]}
|
||||
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":31,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":5},{"id":23,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":5},{"id":24,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":1},{"id":21,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":4},{"id":25,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":2},{"id":19,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":3},{"id":27,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":3},{"id":26,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":8},{"id":29,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":4},{"id":28,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":9},{"id":30,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":10},{"id":15,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":1},{"id":17,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":2}]}
|
||||
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":31,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":4},{"id":23,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":4},{"id":33,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":5},{"id":21,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":3},{"id":25,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":1},{"id":19,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":2},{"id":27,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":2},{"id":26,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":7},{"id":29,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":3},{"id":28,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":8},{"id":30,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":9},{"id":32,"ship_count":1,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":10},{"id":17,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":1}]}
|
||||
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":31,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":3},{"id":23,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":3},{"id":33,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":4},{"id":21,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":2},{"id":34,"ship_count":2,"origin":"tetratos","destination":"tritos","owner":2,"turns_remaining":5},{"id":19,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":1},{"id":27,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":1},{"id":26,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":6},{"id":29,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":2},{"id":28,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":7},{"id":30,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":8},{"id":32,"ship_count":1,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":9}]}
|
||||
{"planets":[{"ship_count":4,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":31,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":2},{"id":23,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":2},{"id":33,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":3},{"id":21,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":1},{"id":34,"ship_count":2,"origin":"tetratos","destination":"tritos","owner":2,"turns_remaining":4},{"id":35,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":5},{"id":32,"ship_count":1,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":8},{"id":26,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":5},{"id":29,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":1},{"id":28,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":6},{"id":30,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":7}]}
|
||||
{"planets":[{"ship_count":5,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":4,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":31,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":1},{"id":23,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":2,"turns_remaining":1},{"id":33,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":2},{"id":36,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":5},{"id":34,"ship_count":2,"origin":"tetratos","destination":"tritos","owner":2,"turns_remaining":3},{"id":35,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":4},{"id":32,"ship_count":1,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":7},{"id":26,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":4},{"id":30,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":6},{"id":28,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":5}]}
|
||||
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":9,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":5,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":37,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":10},{"id":28,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":4},{"id":33,"ship_count":2,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":1},{"id":36,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":4},{"id":34,"ship_count":2,"origin":"tetratos","destination":"tritos","owner":2,"turns_remaining":2},{"id":35,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":3},{"id":32,"ship_count":1,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":6},{"id":26,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":3},{"id":30,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":5}]}
|
||||
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":6,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":37,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":9},{"id":28,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":3},{"id":38,"ship_count":8,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":5},{"id":36,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":3},{"id":34,"ship_count":2,"origin":"tetratos","destination":"tritos","owner":2,"turns_remaining":1},{"id":35,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":2},{"id":32,"ship_count":1,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":5},{"id":26,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":2},{"id":30,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":4}]}
|
||||
{"planets":[{"ship_count":4,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":4,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":37,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":8},{"id":28,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":2},{"id":38,"ship_count":8,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":4},{"id":36,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":2},{"id":39,"ship_count":5,"origin":"tetratos","destination":"tritos","owner":2,"turns_remaining":5},{"id":35,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":1},{"id":32,"ship_count":1,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":4},{"id":26,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":1},{"id":30,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":3}]}
|
||||
{"planets":[{"ship_count":5,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":0,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":37,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":7},{"id":28,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":1},{"id":38,"ship_count":8,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":3},{"id":36,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":1},{"id":39,"ship_count":5,"origin":"tetratos","destination":"tritos","owner":2,"turns_remaining":4},{"id":40,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":5},{"id":32,"ship_count":1,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":3},{"id":30,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":2}]}
|
||||
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":4,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":0,"x":6.0,"y":0.0,"owner":null,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":37,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":6},{"id":41,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":10},{"id":38,"ship_count":8,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":2},{"id":30,"ship_count":2,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":1},{"id":39,"ship_count":5,"origin":"tetratos","destination":"tritos","owner":2,"turns_remaining":3},{"id":40,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":4},{"id":32,"ship_count":1,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":2}]}
|
||||
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":37,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":5},{"id":41,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":9},{"id":38,"ship_count":8,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":1},{"id":42,"ship_count":3,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":5},{"id":39,"ship_count":5,"origin":"tetratos","destination":"tritos","owner":2,"turns_remaining":2},{"id":40,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":3},{"id":32,"ship_count":1,"origin":"duteros","destination":"tetratos","owner":1,"turns_remaining":1}]}
|
||||
{"planets":[{"ship_count":4,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":11,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":1,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":37,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":4},{"id":41,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":8},{"id":44,"ship_count":3,"origin":"duteros","destination":"tetratos","owner":2,"turns_remaining":10},{"id":42,"ship_count":3,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":4},{"id":39,"ship_count":5,"origin":"tetratos","destination":"tritos","owner":2,"turns_remaining":1},{"id":40,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":2},{"id":43,"ship_count":1,"origin":"tetratos","destination":"tritos","owner":1,"turns_remaining":5}]}
|
||||
{"planets":[{"ship_count":5,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":7,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":37,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":3},{"id":41,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":7},{"id":44,"ship_count":3,"origin":"duteros","destination":"tetratos","owner":2,"turns_remaining":9},{"id":42,"ship_count":3,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":3},{"id":46,"ship_count":10,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":5},{"id":40,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":1},{"id":43,"ship_count":1,"origin":"tetratos","destination":"tritos","owner":1,"turns_remaining":4},{"id":45,"ship_count":2,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":10}]}
|
||||
{"planets":[{"ship_count":6,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":37,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":2},{"id":41,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":6},{"id":44,"ship_count":3,"origin":"duteros","destination":"tetratos","owner":2,"turns_remaining":8},{"id":42,"ship_count":3,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":2},{"id":46,"ship_count":10,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":4},{"id":48,"ship_count":6,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":5},{"id":43,"ship_count":1,"origin":"tetratos","destination":"tritos","owner":1,"turns_remaining":3},{"id":45,"ship_count":2,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":9},{"id":47,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":10}]}
|
||||
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":7,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":37,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":1},{"id":41,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":5},{"id":44,"ship_count":3,"origin":"duteros","destination":"tetratos","owner":2,"turns_remaining":7},{"id":42,"ship_count":3,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":1},{"id":46,"ship_count":10,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":3},{"id":48,"ship_count":6,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":4},{"id":43,"ship_count":1,"origin":"tetratos","destination":"tritos","owner":1,"turns_remaining":2},{"id":45,"ship_count":2,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":8},{"id":47,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":9},{"id":49,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":10},{"id":50,"ship_count":5,"origin":"protos","destination":"tetratos","owner":2,"turns_remaining":11}]}
|
||||
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":52,"ship_count":6,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":5},{"id":41,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":4},{"id":44,"ship_count":3,"origin":"duteros","destination":"tetratos","owner":2,"turns_remaining":6},{"id":51,"ship_count":1,"origin":"tetratos","destination":"protos","owner":1,"turns_remaining":11},{"id":46,"ship_count":10,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":2},{"id":48,"ship_count":6,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":3},{"id":43,"ship_count":1,"origin":"tetratos","destination":"tritos","owner":1,"turns_remaining":1},{"id":45,"ship_count":2,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":7},{"id":47,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":8},{"id":49,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":9},{"id":50,"ship_count":5,"origin":"protos","destination":"tetratos","owner":2,"turns_remaining":10}]}
|
||||
{"planets":[{"ship_count":4,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":52,"ship_count":6,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":4},{"id":41,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":3},{"id":44,"ship_count":3,"origin":"duteros","destination":"tetratos","owner":2,"turns_remaining":5},{"id":51,"ship_count":1,"origin":"tetratos","destination":"protos","owner":1,"turns_remaining":10},{"id":46,"ship_count":10,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":1},{"id":48,"ship_count":6,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":2},{"id":53,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":11},{"id":45,"ship_count":2,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":6},{"id":47,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":7},{"id":49,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":8},{"id":50,"ship_count":5,"origin":"protos","destination":"tetratos","owner":2,"turns_remaining":9}]}
|
||||
{"planets":[{"ship_count":5,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":13,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":52,"ship_count":6,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":3},{"id":41,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":2},{"id":44,"ship_count":3,"origin":"duteros","destination":"tetratos","owner":2,"turns_remaining":4},{"id":51,"ship_count":1,"origin":"tetratos","destination":"protos","owner":1,"turns_remaining":9},{"id":54,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":9},{"id":48,"ship_count":6,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":1},{"id":53,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":10},{"id":45,"ship_count":2,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":5},{"id":47,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":6},{"id":49,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":7},{"id":50,"ship_count":5,"origin":"protos","destination":"tetratos","owner":2,"turns_remaining":8}]}
|
||||
{"planets":[{"ship_count":6,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":3,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":8,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":52,"ship_count":6,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":2},{"id":41,"ship_count":4,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":1},{"id":44,"ship_count":3,"origin":"duteros","destination":"tetratos","owner":2,"turns_remaining":3},{"id":51,"ship_count":1,"origin":"tetratos","destination":"protos","owner":1,"turns_remaining":8},{"id":54,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":8},{"id":55,"ship_count":12,"origin":"tetratos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":53,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":9},{"id":45,"ship_count":2,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":4},{"id":47,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":5},{"id":49,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":6},{"id":50,"ship_count":5,"origin":"protos","destination":"tetratos","owner":2,"turns_remaining":7}]}
|
||||
{"planets":[{"ship_count":7,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":8,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":52,"ship_count":6,"origin":"tritos","destination":"tetratos","owner":2,"turns_remaining":1},{"id":56,"ship_count":7,"origin":"tetratos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":44,"ship_count":3,"origin":"duteros","destination":"tetratos","owner":2,"turns_remaining":2},{"id":51,"ship_count":1,"origin":"tetratos","destination":"protos","owner":1,"turns_remaining":7},{"id":54,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":7},{"id":55,"ship_count":12,"origin":"tetratos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":53,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":8},{"id":45,"ship_count":2,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":3},{"id":47,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":4},{"id":49,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":5},{"id":50,"ship_count":5,"origin":"protos","destination":"tetratos","owner":2,"turns_remaining":6}]}
|
||||
{"planets":[{"ship_count":8,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":9,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":57,"ship_count":7,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":9},{"id":56,"ship_count":7,"origin":"tetratos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":44,"ship_count":3,"origin":"duteros","destination":"tetratos","owner":2,"turns_remaining":1},{"id":51,"ship_count":1,"origin":"tetratos","destination":"protos","owner":1,"turns_remaining":6},{"id":54,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":6},{"id":55,"ship_count":12,"origin":"tetratos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":53,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":7},{"id":45,"ship_count":2,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":2},{"id":47,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":3},{"id":49,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":4},{"id":50,"ship_count":5,"origin":"protos","destination":"tetratos","owner":2,"turns_remaining":5}]}
|
||||
{"planets":[{"ship_count":9,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":7,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":3,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":5,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":57,"ship_count":7,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":8},{"id":56,"ship_count":7,"origin":"tetratos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":58,"ship_count":8,"origin":"tetratos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":51,"ship_count":1,"origin":"tetratos","destination":"protos","owner":1,"turns_remaining":5},{"id":54,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":55,"ship_count":12,"origin":"tetratos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":53,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":6},{"id":45,"ship_count":2,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":1},{"id":47,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":2},{"id":49,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":3},{"id":50,"ship_count":5,"origin":"protos","destination":"tetratos","owner":2,"turns_remaining":4}]}
|
||||
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":4,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":6,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":57,"ship_count":7,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":7},{"id":56,"ship_count":7,"origin":"tetratos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":58,"ship_count":8,"origin":"tetratos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":51,"ship_count":1,"origin":"tetratos","destination":"protos","owner":1,"turns_remaining":4},{"id":54,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":55,"ship_count":12,"origin":"tetratos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":53,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":5},{"id":59,"ship_count":8,"origin":"protos","destination":"pemptos","owner":2,"turns_remaining":10},{"id":47,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":1},{"id":49,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":2},{"id":50,"ship_count":5,"origin":"protos","destination":"tetratos","owner":2,"turns_remaining":3}]}
|
||||
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":5,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":7,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":57,"ship_count":7,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":6},{"id":56,"ship_count":7,"origin":"tetratos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":58,"ship_count":8,"origin":"tetratos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":51,"ship_count":1,"origin":"tetratos","destination":"protos","owner":1,"turns_remaining":3},{"id":54,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":60,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":11},{"id":53,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":4},{"id":59,"ship_count":8,"origin":"protos","destination":"pemptos","owner":2,"turns_remaining":9},{"id":50,"ship_count":5,"origin":"protos","destination":"tetratos","owner":2,"turns_remaining":2},{"id":49,"ship_count":1,"origin":"tetratos","destination":"duteros","owner":1,"turns_remaining":1}]}
|
||||
{"planets":[{"ship_count":4,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":14,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":57,"ship_count":7,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":61,"ship_count":6,"origin":"tetratos","destination":"extos","owner":2,"turns_remaining":10},{"id":58,"ship_count":8,"origin":"tetratos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":51,"ship_count":1,"origin":"tetratos","destination":"protos","owner":1,"turns_remaining":2},{"id":54,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":60,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":10},{"id":53,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":3},{"id":59,"ship_count":8,"origin":"protos","destination":"pemptos","owner":2,"turns_remaining":8},{"id":50,"ship_count":5,"origin":"protos","destination":"tetratos","owner":2,"turns_remaining":1}]}
|
||||
{"planets":[{"ship_count":5,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":7,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":8,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":57,"ship_count":7,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":61,"ship_count":6,"origin":"tetratos","destination":"extos","owner":2,"turns_remaining":9},{"id":58,"ship_count":8,"origin":"tetratos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":51,"ship_count":1,"origin":"tetratos","destination":"protos","owner":1,"turns_remaining":1},{"id":54,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":60,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":9},{"id":53,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":2},{"id":59,"ship_count":8,"origin":"protos","destination":"pemptos","owner":2,"turns_remaining":7},{"id":62,"ship_count":13,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":5}]}
|
||||
{"planets":[{"ship_count":5,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":8,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetratos"},{"ship_count":16,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":57,"ship_count":7,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":61,"ship_count":6,"origin":"tetratos","destination":"extos","owner":2,"turns_remaining":8},{"id":63,"ship_count":7,"origin":"tetratos","destination":"extos","owner":2,"turns_remaining":10},{"id":62,"ship_count":13,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":4},{"id":59,"ship_count":8,"origin":"protos","destination":"pemptos","owner":2,"turns_remaining":6},{"id":60,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":8},{"id":53,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":1}]}
|
114
web/pw-frontend/public/static/res/assets/earth.svg
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
web/pw-frontend/public/static/res/assets/font.png
Normal file
After Width: | Height: | Size: 912 B |
118
web/pw-frontend/public/static/res/assets/jupiter.svg
Normal file
|
@ -0,0 +1,118 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 493.0475 493.16002"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="jupiter-with-satellite.svg"
|
||||
width="493.04749"
|
||||
height="493.16"
|
||||
inkscape:version="0.92.1 r15371"><metadata
|
||||
id="metadata45"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs43" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1536"
|
||||
inkscape:window-height="801"
|
||||
id="namedview41"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.38562218"
|
||||
inkscape:cx="-121.54471"
|
||||
inkscape:cy="246.58001"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g8" />
|
||||
<g
|
||||
id="g8"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
<path
|
||||
d="M 539.776,131.64 C 493.205,85.067 431.282,59.419 365.417,59.419 c -65.865,0 -127.785,25.649 -174.359,72.221 -96.142,96.142 -96.142,252.575 0,348.718 46.573,46.573 108.494,72.221 174.359,72.221 65.865,0 127.786,-25.648 174.359,-72.221 46.574,-46.573 72.223,-108.494 72.223,-174.359 0,-65.865 -25.647,-127.786 -72.223,-174.359 z M 375.169,405.983 c -12.849,11.452 -28.27,18.565 -40.247,18.565 -3.901,0 -9.259,-0.794 -12.626,-4.57 -3.823,-4.287 -4.311,-11.821 -1.337,-20.669 3.484,-10.375 11.047,-21.12 21.292,-30.252 12.849,-11.452 28.27,-18.565 40.247,-18.565 3.901,0 9.259,0.794 12.626,4.568 9.699,10.882 -2.733,35.57 -19.955,50.923 z m -59.521,27.38 c 5.126,3.72 11.674,5.68 19.274,5.68 15.617,0 34.268,-8.313 49.89,-22.24 23.566,-21.006 33.496,-48.135 25.096,-65.431 0.069,-0.069 0.138,-0.134 0.205,-0.203 l 0.245,-0.245 c 56.354,-56.355 104.89,-119.767 140.932,-183.964 9.652,12.849 17.879,26.565 24.597,40.957 -35.262,61.327 -80.521,119.83 -134.614,173.92 -54.098,54.099 -112.607,99.362 -173.935,134.623 -14.394,-6.719 -28.111,-14.945 -40.961,-24.599 30.178,-16.937 60.136,-36.571 89.271,-58.498 z M 466.754,97.09 c -35.38,61.735 -80.828,120.58 -135.241,174.991 -54.389,54.389 -113.209,99.824 -174.915,135.197 -5.757,-11.897 -10.44,-24.186 -14.05,-36.725 56.493,-34.46 110.419,-77.182 160.338,-127.099 49.957,-49.957 92.703,-103.921 127.17,-160.452 12.628,3.642 24.897,8.353 36.698,14.088 z m -265.444,44.8 c 43.835,-43.835 102.116,-67.977 164.109,-67.977 7.242,0 14.43,0.342 21.555,0.995 -31.234,48.087 -68.655,94.211 -111.341,137.176 -2.821,2.839 -2.807,7.429 0.034,10.25 1.413,1.404 3.262,2.107 5.108,2.107 1.863,0 3.725,-0.714 5.142,-2.14 44.565,-44.857 84.642,-94.977 116.958,-145.384 4.187,0.676 8.346,1.459 12.472,2.359 -33.458,54.163 -74.692,105.911 -122.709,153.927 -47.981,47.981 -99.69,89.192 -153.82,122.642 -16.314,-74.713 4.517,-155.981 62.492,-213.955 z m -37.988,278.24 c 62.996,-36.051 123.004,-82.362 178.439,-137.797 55.457,-55.457 101.781,-115.487 137.837,-178.506 18.062,10.238 34.849,22.985 49.928,38.064 4.164,4.164 8.148,8.46 11.953,12.874 -35.656,64.768 -84.421,128.944 -141.318,185.854 -4.865,-3.019 -10.834,-4.622 -17.665,-4.622 -15.617,0 -34.269,8.313 -49.892,22.24 -12.097,10.783 -21.113,23.731 -25.389,36.457 -3.457,10.294 -3.575,19.665 -0.495,27.248 -30.198,22.709 -61.277,42.902 -92.54,60.113 -4.414,-3.803 -8.708,-7.786 -12.872,-11.95 -15.228,-15.229 -27.882,-32.071 -37.986,-49.975 z m 366.205,49.976 c -43.835,43.835 -102.116,67.977 -164.109,67.977 -15.161,0 -30.098,-1.453 -44.659,-4.276 18.864,-11.87 37.661,-24.833 55.998,-38.625 3.2,-2.406 3.841,-6.951 1.435,-10.149 -2.406,-3.2 -6.952,-3.84 -10.149,-1.435 -19.855,14.934 -46.393,32.45 -67.363,45.368 -5.606,-1.62 -11.142,-3.448 -16.596,-5.487 58.968,-35.049 115.237,-79.19 167.435,-131.388 52.192,-52.19 96.333,-108.454 131.381,-167.423 2.049,5.485 3.887,11.051 5.512,16.69 -23.941,38.799 -55.866,83.002 -87.51,118.944 -2.645,3.004 -2.356,7.585 0.649,10.228 1.379,1.212 3.086,1.808 4.787,1.808 2.009,0 4.012,-0.832 5.443,-2.459 30.673,-34.837 58.031,-71.308 81.446,-108.536 2.821,14.559 4.276,29.493 4.276,44.652 10e-4,61.995 -24.139,120.276 -67.976,164.111 z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0" />
|
||||
|
||||
<path
|
||||
d="m 337.815,406.147 c -4.829,-5.418 0.615,-18.151 12.159,-28.441 11.544,-10.29 24.817,-14.24 29.646,-8.822 4.829,5.417 -0.615,18.151 -12.159,28.441 -11.545,10.29 -24.817,14.24 -29.646,8.822 z"
|
||||
id="path6"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
id="g10"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g12"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g14"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g16"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g18"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g20"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g22"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g24"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g26"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g28"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g30"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g32"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g34"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g36"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
<g
|
||||
id="g38"
|
||||
transform="translate(-118.9515,-59.419)">
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.9 KiB |
BIN
web/pw-frontend/public/static/res/assets/leaves.jpg
Normal file
After Width: | Height: | Size: 36 KiB |
114
web/pw-frontend/public/static/res/assets/mars.svg
Normal file
|
@ -0,0 +1,114 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 272.17 272.17"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="mars-with-satellite.svg"
|
||||
width="272.17001"
|
||||
height="272.17001"
|
||||
inkscape:version="0.92.1 r15371"><metadata
|
||||
id="metadata43"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs41" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1536"
|
||||
inkscape:window-height="801"
|
||||
id="namedview39"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.74916113"
|
||||
inkscape:cx="-15.912826"
|
||||
inkscape:cy="157.50949"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g6" />
|
||||
<g
|
||||
id="g6"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
<path
|
||||
d="m 150.663,42.849 c -75.037,0 -136.085,61.047 -136.085,136.085 0,75.038 61.048,136.085 136.085,136.085 75.037,0 136.085,-61.048 136.085,-136.085 0,-75.037 -61.048,-136.085 -136.085,-136.085 z m 94.519,49.737 C 215.47,98.072 194.155,95.67 181.775,85.417 166.119,72.442 142.824,62.802 112.41,56.684 c 12.085,-3.79 24.935,-5.835 38.253,-5.835 37.388,0 71.082,16.104 94.519,41.737 z M 49.864,99.992 c 7.659,4.116 14.848,7.336 20.496,9.16 l 1.405,0.455 c 11.474,3.718 26.173,8.48 38.353,8.48 9.974,0 18.259,-3.194 21.701,-12.769 1.564,-4.354 1.492,-8.272 -0.214,-11.644 -3.639,-7.188 -13.464,-10.107 -25.902,-13.801 -2.913,-0.865 -5.924,-1.76 -8.986,-2.75 -4.31,-1.395 -10.33,-3.021 -17.181,-4.657 5.813,-3.896 11.958,-7.332 18.388,-10.249 35.034,5.547 62.249,15.687 78.747,29.361 9.52,7.883 23.149,11.833 40.721,11.833 9.978,0 21.246,-1.291 33.734,-3.842 3.017,3.811 5.819,7.799 8.394,11.942 -7.815,0.09 -15.483,0.207 -23.256,0.357 -32.772,0.63 -51.646,9.594 -69.899,18.262 -16.304,7.742 -31.704,15.056 -56.158,15.056 -19.363,0 -45.543,-6.853 -75.875,-19.812 4.196,-9.082 9.42,-17.595 15.532,-25.382 z M 71.002,78.711 c 9.393,2.083 17.789,4.256 23.251,6.023 3.154,1.021 6.213,1.929 9.171,2.808 9.751,2.896 18.96,5.631 21.043,9.745 0.436,0.861 0.892,2.351 -0.177,5.326 -4.637,12.897 -27.272,6.767 -50.06,-0.616 L 72.82,101.54 C 67.967,99.972 61.794,97.234 55.123,93.723 59.98,88.283 65.292,83.259 71.002,78.711 Z M 23.02,168.333 c 35.942,5.647 57.003,15.954 59.452,29.178 0.284,1.535 -0.071,2.922 -1.119,4.364 -2.927,4.03 -13.653,11.492 -52.407,16.946 -4.126,-12.559 -6.367,-25.966 -6.367,-39.887 -0.001,-3.57 0.153,-7.104 0.441,-10.601 z m 23.365,84.896 c 22.439,-3.993 52.181,-14.162 77.357,-39.338 42.857,-42.857 53.898,-42.857 78.089,-42.857 9.532,0 21.889,5.026 34.971,10.348 13.57,5.52 27.555,11.194 41.059,12.592 -0.781,6.647 -2.069,13.141 -3.832,19.44 -9.441,0.149 -18.893,-1.263 -28.848,-2.765 -23.035,-3.475 -49.144,-7.414 -80.863,8.749 -36.661,18.676 -56.554,50.852 -67.026,75.957 -20.42,-9.398 -37.963,-24.01 -50.907,-42.126 z m 68.931,48.827 c -3.62,-1.041 -7.173,-2.242 -10.656,-3.586 9.935,-23.833 28.755,-54.35 63.288,-71.943 29.436,-14.998 53.129,-11.422 76.039,-7.966 9.394,1.417 18.359,2.748 27.51,2.855 -2.915,8.266 -6.65,16.149 -11.117,23.543 -29.036,-6.441 -59.028,-1.667 -89.203,14.214 -24.231,12.752 -43.497,30.024 -55.861,42.883 z m 35.347,4.963 c -9.027,0 -17.837,-0.944 -26.341,-2.729 11.947,-11.958 29.304,-26.84 50.581,-38.037 27.413,-14.427 54.562,-19.154 80.787,-14.093 -23.175,33.139 -61.609,54.859 -105.027,54.859 z M 278.55,186.003 c -12.347,-1.311 -25.739,-6.745 -38.734,-12.031 -13.827,-5.625 -26.889,-10.938 -37.985,-10.938 -27.418,0 -40.278,1.733 -83.745,45.2 -25.043,25.043 -54.972,34.354 -76.548,37.691 -3.79,-6.151 -7.074,-12.644 -9.795,-19.422 31.269,-4.529 49.643,-11.06 56.083,-19.926 2.324,-3.201 3.193,-6.839 2.513,-10.521 -3.943,-21.297 -37.42,-31.136 -66.412,-35.676 1.399,-9.598 3.865,-18.853 7.275,-27.643 31.702,13.558 58.277,20.448 79.003,20.448 26.258,0 42.448,-7.689 59.59,-15.83 17.488,-8.305 35.571,-16.893 66.622,-17.49 9.222,-0.177 18.305,-0.308 27.659,-0.402 9.362,17.782 14.672,38.016 14.672,59.47 0,2.373 -0.07,4.729 -0.198,7.07 z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0" />
|
||||
|
||||
</g>
|
||||
<g
|
||||
id="g8"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g10"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g12"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g14"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g16"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g18"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g20"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g22"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g24"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g26"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g28"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g30"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g32"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g34"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
<g
|
||||
id="g36"
|
||||
transform="translate(-14.578,-42.849)">
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.6 KiB |
186
web/pw-frontend/public/static/res/assets/neptune.svg
Normal file
|
@ -0,0 +1,186 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 272.044 272.17001"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="neptune-with-satellite.svg"
|
||||
width="272.04401"
|
||||
height="272.17001"
|
||||
inkscape:version="0.92.1 r15371"><metadata
|
||||
id="metadata79"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs77" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1536"
|
||||
inkscape:window-height="801"
|
||||
id="namedview75"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.75655574"
|
||||
inkscape:cx="-13.59678"
|
||||
inkscape:cy="155.969"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g42" />
|
||||
<g
|
||||
id="g42"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
<path
|
||||
d="m 148.297,39.769 c -36.35,0 -70.524,14.155 -96.227,39.858 -53.06,53.06 -53.06,139.394 0,192.454 25.703,25.703 59.877,39.858 96.227,39.858 36.35,0 70.524,-14.155 96.227,-39.858 53.06,-53.06 53.06,-139.394 0,-192.454 C 218.821,53.924 184.647,39.769 148.297,39.769 Z M 271.474,165.86 c -8.235,-5.915 -18.998,-2.783 -29.532,8.588 -8.691,9.382 -15.31,21.945 -19.67,37.341 -0.602,2.125 0.633,4.336 2.759,4.938 2.127,0.601 4.336,-0.634 4.938,-2.759 4.013,-14.169 10.016,-25.637 17.842,-34.084 3.54,-3.822 12.475,-12.208 18.997,-7.527 8.074,5.799 7.154,21.44 6.385,27.895 -1.709,14.318 -7.573,26.757 -15.687,33.274 -2.358,1.895 -5.645,3.751 -7.902,1.84 -2.635,-2.23 -3.822,-7.371 -3.344,-14.476 0.148,-2.204 -1.519,-4.111 -3.723,-4.26 -2.226,-0.138 -4.111,1.519 -4.26,3.723 -0.672,9.986 1.399,17.091 6.158,21.119 2.164,1.832 4.646,2.741 7.302,2.741 1.832,0 3.748,-0.447 5.699,-1.306 -5.142,8.369 -11.327,16.273 -18.569,23.516 -1.59,1.59 -3.216,3.13 -4.873,4.625 -3.667,-4.799 -6.198,-12.047 -7.225,-20.88 -0.256,-2.194 -2.241,-3.763 -4.437,-3.511 -2.194,0.255 -3.766,2.241 -3.511,4.436 1.23,10.565 4.34,19.14 9.059,25.132 -16.61,13.223 -36.039,21.995 -56.813,25.702 5.189,-6.479 10.531,-16.472 12.156,-31.099 0.244,-2.196 -1.338,-4.173 -3.534,-4.417 -2.186,-0.244 -4.173,1.338 -4.417,3.534 -2.288,20.594 -12.727,30.327 -17.241,33.631 -3.223,0.241 -6.469,0.364 -9.735,0.364 -34.213,0 -66.378,-13.323 -90.57,-37.516 -33.004,-33.004 -44.189,-79.685 -33.57,-121.967 11.195,1.303 26.82,4.299 43.035,11.16 0.509,0.215 1.037,0.317 1.557,0.317 1.559,0 3.04,-0.917 3.686,-2.442 0.861,-2.034 -0.09,-4.381 -2.125,-5.242 C 53.868,141.293 38.021,138.111 26.373,136.664 32.383,117.86 42.832,100.179 57.727,85.285 68.941,74.071 81.87,65.197 95.92,58.898 c -0.781,0.832 -1.538,1.704 -2.252,2.627 -5.132,6.638 -6.665,13.818 -4.432,20.764 0.676,2.103 2.932,3.261 5.032,2.584 2.104,-0.676 3.26,-2.929 2.584,-5.032 -3.119,-9.701 6.766,-18.895 16.179,-23.821 8.789,-4.599 19.379,-7.341 31.542,-8.193 1.239,-0.035 2.48,-0.058 3.724,-0.058 12.251,0 24.237,1.717 35.691,5.022 2.36,0.884 4.63,1.872 6.793,2.972 5.949,3.025 9.001,6.12 9.604,9.737 0.85,5.096 -4.18,9.225 -6.381,10.763 -11.526,8.055 -26.655,7.89 -37.317,6.332 -2.189,-0.324 -4.217,1.194 -4.536,3.38 -0.319,2.186 1.194,4.217 3.38,4.536 3.699,0.54 7.881,0.924 12.299,0.924 10.028,0 21.264,-1.981 30.757,-8.614 7.284,-5.089 10.815,-11.882 9.689,-18.635 -0.103,-0.615 -0.243,-1.208 -0.409,-1.783 8.589,4.523 16.694,10.047 24.165,16.52 -8.145,14.582 -23.589,20.575 -35.122,23.032 -2.16,0.46 -3.538,2.585 -3.078,4.746 0.4,1.88 2.061,3.167 3.908,3.167 0.276,0 0.557,-0.029 0.838,-0.089 12.722,-2.711 29.678,-9.305 39.469,-25.296 0.273,0.269 0.551,0.531 0.823,0.803 23.661,23.662 36.104,54.354 37.344,85.415 -1.287,-1.834 -2.844,-3.479 -4.74,-4.841 z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 137.556,85.235 c 0.603,0.324 1.251,0.478 1.891,0.478 1.425,0 2.804,-0.764 3.526,-2.106 1.046,-1.946 0.317,-4.371 -1.628,-5.417 -1.062,-0.571 -6.264,-3.626 -4.383,-7.716 1.226,-2.667 4.829,-4.64 11.012,-6.032 6.876,-1.548 17.445,-1.943 24.605,2.034 1.188,0.66 1.884,1.448 1.862,2.11 -0.027,0.803 -0.928,2.024 -2.877,2.94 -2,0.94 -2.858,3.322 -1.919,5.322 0.94,1.999 3.322,2.859 5.321,1.918 4.54,-2.133 7.332,-5.838 7.47,-9.91 0.128,-3.778 -2.05,-7.195 -5.973,-9.374 -9.12,-5.066 -21.604,-4.792 -30.247,-2.845 -5.602,1.261 -13.409,3.721 -16.523,10.494 -3.061,6.654 0.099,13.93 7.863,18.104 z"
|
||||
id="path4"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 100.492,96.756 c 2.997,2.273 6.354,4.294 10.263,6.181 0.561,0.271 1.152,0.398 1.735,0.398 1.487,0 2.916,-0.833 3.605,-2.263 0.96,-1.99 0.125,-4.381 -1.864,-5.341 -3.424,-1.652 -6.337,-3.402 -8.906,-5.35 -1.76,-1.335 -4.27,-0.991 -5.604,0.77 -1.334,1.762 -0.989,4.271 0.771,5.605 z"
|
||||
id="path6"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 179.091,111.757 c 0.047,10e-4 4.807,-0.026 7.63,-0.253 2.202,-0.177 3.844,-2.106 3.667,-4.308 -0.177,-2.203 -2.137,-3.843 -4.308,-3.667 -4.037,0.325 -6.639,0.235 -6.68,0.233 -2.181,-0.089 -4.063,1.634 -4.149,3.84 -0.086,2.208 1.633,4.068 3.84,4.155 z"
|
||||
id="path8"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 201.867,133.619 c 0.336,0 9.337,-2.448 13.524,-3.81 2.101,-0.683 3.25,-2.94 2.566,-5.041 -0.684,-2.101 -2.938,-3.25 -5.041,-2.567 -4.04,1.314 -8.099,2.507 -12.062,3.547 -2.138,0.561 -3.415,2.748 -2.854,4.884 0.472,1.798 2.092,2.987 3.867,2.987 z"
|
||||
id="path10"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 187.617,128.737 c -46.298,8.716 -77.082,-4.029 -94.75,-16.257 -1.817,-1.257 -4.309,-0.804 -5.565,1.013 -1.257,1.816 -0.804,4.308 1.013,5.565 14.605,10.108 37.502,20.561 69.73,20.561 9.526,0 19.871,-0.914 31.054,-3.02 2.171,-0.409 3.6,-2.5 3.19,-4.671 -0.41,-2.172 -2.508,-3.602 -4.672,-3.191 z"
|
||||
id="path12"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 77.141,110.083 c 0.771,0.723 1.753,1.081 2.733,1.081 1.068,0 2.133,-0.425 2.92,-1.266 1.51,-1.612 1.427,-4.144 -0.185,-5.654 -3.733,-3.497 -5.615,-5.951 -5.675,-6.029 -1.327,-1.763 -3.831,-2.119 -5.596,-0.795 -1.768,1.326 -2.125,3.833 -0.8,5.6 0.092,0.121 2.267,3.001 6.603,7.063 z"
|
||||
id="path14"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 41.149,171.992 c -1.633,-0.278 -3.294,-0.535 -4.938,-0.763 -2.188,-0.302 -4.208,1.224 -4.512,3.411 -0.304,2.188 1.223,4.208 3.412,4.513 1.563,0.217 5.149,0.783 5.373,0.783 1.915,0 3.607,-1.379 3.938,-3.33 0.37,-2.178 -1.095,-4.244 -3.273,-4.614 z"
|
||||
id="path16"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 53.789,182.977 c 13.524,3.751 45.748,15.723 52.875,45.778 0.436,1.839 2.077,3.078 3.889,3.078 0.306,0 0.616,-0.035 0.926,-0.109 2.149,-0.51 3.479,-2.666 2.969,-4.815 -3.121,-13.162 -10.671,-24.582 -22.441,-33.944 -9.71,-7.724 -22.186,-13.843 -36.079,-17.697 -2.125,-0.589 -4.333,0.656 -4.924,2.785 -0.59,2.129 0.656,4.333 2.785,4.924 z"
|
||||
id="path18"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 110.315,242.16 c -2.004,-0.927 -4.382,-0.057 -5.311,1.948 -1.013,2.187 -2.39,4.152 -4.093,5.843 -1.568,1.557 -1.577,4.089 -0.02,5.657 0.782,0.788 1.81,1.182 2.838,1.182 1.019,0 2.039,-0.387 2.818,-1.162 2.378,-2.362 4.301,-5.106 5.715,-8.157 0.929,-2.005 0.057,-4.383 -1.947,-5.311 z"
|
||||
id="path20"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 90.255,255.468 c -8.356,1.642 -17.778,-1.182 -24.588,-7.365 -12.756,-11.582 -12.75,-24.255 -8.729,-29.174 3.817,-4.669 8.713,-5.013 12.147,-4.479 6.578,1.022 13.085,6.143 15.473,12.175 0.813,2.054 3.139,3.062 5.191,2.247 2.054,-0.813 3.06,-3.137 2.247,-5.191 -3.473,-8.774 -12.187,-15.66 -21.683,-17.136 -7.773,-1.208 -14.724,1.392 -19.57,7.321 -10.192,12.469 -0.554,30.991 9.545,40.16 6.995,6.351 16.232,9.895 25.219,9.894 2.12,0 4.228,-0.197 6.288,-0.602 2.168,-0.426 3.58,-2.528 3.155,-4.696 -0.425,-2.167 -2.526,-3.58 -4.695,-3.154 z"
|
||||
id="path22"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 82.824,236.937 c -2.256,1.781 -4.846,1.359 -6.622,0.692 -3.652,-1.372 -6.874,-4.924 -7.496,-8.263 -0.404,-2.171 -2.489,-3.603 -4.665,-3.2 -2.172,0.405 -3.604,2.493 -3.2,4.665 1.129,6.061 6.289,11.936 12.547,14.287 1.924,0.723 3.86,1.08 5.739,1.08 3.157,0 6.152,-1.008 8.651,-2.98 1.734,-1.368 2.031,-3.883 0.663,-5.618 -1.367,-1.735 -3.883,-2.032 -5.617,-0.663 z"
|
||||
id="path24"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 109.058,172.892 c -1.629,-1.493 -4.159,-1.385 -5.652,0.243 -1.494,1.628 -1.385,4.158 0.243,5.652 10.774,9.886 29.278,29.985 32.162,53.524 1.465,11.963 -1.974,23.543 -9.683,32.606 -3.238,3.808 -6.859,6.886 -10.763,9.15 -1.911,1.108 -2.562,3.556 -1.453,5.467 0.742,1.279 2.084,1.994 3.464,1.994 0.681,0 1.372,-0.174 2.003,-0.541 4.693,-2.722 9.014,-6.385 12.843,-10.887 9.176,-10.787 13.271,-24.552 11.53,-38.762 -3.196,-26.086 -23.109,-47.815 -34.694,-58.446 z"
|
||||
id="path26"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 94.011,170.834 c 0.716,0.531 1.551,0.788 2.379,0.788 1.223,0 2.431,-0.56 3.216,-1.618 1.316,-1.774 0.944,-4.28 -0.831,-5.595 -1.901,-1.41 -3.876,-2.792 -5.871,-4.108 -1.844,-1.217 -4.325,-0.708 -5.542,1.135 -1.217,1.844 -0.708,4.325 1.135,5.542 1.874,1.235 3.729,2.533 5.514,3.856 z"
|
||||
id="path28"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 151.585,173.576 c -1.26,-1.815 -3.749,-2.266 -5.564,-1.009 -1.815,1.257 -2.268,3.749 -1.012,5.564 0.312,0.451 30.974,45.477 13.988,80.185 -0.971,1.984 -0.149,4.38 1.835,5.351 0.565,0.277 1.165,0.408 1.755,0.408 1.479,0 2.901,-0.824 3.596,-2.243 7.945,-16.236 7.9,-36.706 -0.13,-59.195 -5.964,-16.7 -14.125,-28.565 -14.468,-29.061 z"
|
||||
id="path30"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 257.729,197.605 c 2.204,-1.072 3.393,3.135 3.063,8.028 -0.148,2.204 1.518,4.112 3.722,4.26 0.092,0.006 0.183,0.009 0.273,0.009 2.086,0 3.845,-1.618 3.987,-3.73 0.482,-7.146 -1.438,-12.739 -5.267,-15.344 -2.692,-1.832 -5.965,-1.991 -9.21,-0.45 -1.996,0.948 -2.845,3.334 -1.897,5.33 0.948,1.996 3.344,2.863 5.329,1.897 z"
|
||||
id="path32"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 219.052,227.503 c -0.246,1.928 -0.436,3.879 -0.563,5.801 -0.147,2.204 1.521,4.11 3.725,4.257 0.091,0.006 0.181,0.009 0.271,0.009 2.088,0 3.846,-1.62 3.987,-3.734 0.117,-1.762 0.291,-3.552 0.517,-5.322 0.279,-2.191 -1.271,-4.194 -3.463,-4.473 -2.187,-0.282 -4.195,1.272 -4.474,3.462 z"
|
||||
id="path34"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 215.557,170.546 c -1.205,1.852 -0.681,4.33 1.171,5.535 0.674,0.438 1.43,0.647 2.178,0.647 1.309,0 2.59,-0.641 3.356,-1.819 11.387,-17.501 23.308,-27.803 36.441,-31.495 2.127,-0.598 3.366,-2.806 2.769,-4.933 -0.598,-2.126 -2.809,-3.368 -4.933,-2.768 -15.084,4.24 -28.491,15.634 -40.982,34.833 z"
|
||||
id="path36"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 206.98,213.368 c 0.409,-2.171 -1.019,-4.263 -3.189,-4.672 -2.163,-0.412 -4.263,1.018 -4.672,3.189 -6.977,36.974 4.454,68.118 4.943,69.425 0.603,1.606 2.126,2.596 3.745,2.596 0.466,0 0.939,-0.082 1.4,-0.254 2.068,-0.773 3.118,-3.077 2.348,-5.146 -0.112,-0.3 -11.122,-30.441 -4.575,-65.138 z"
|
||||
id="path38"
|
||||
inkscape:connector-curvature="0" />
|
||||
|
||||
</g>
|
||||
<g
|
||||
id="g44"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g46"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g48"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g50"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g52"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g54"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g56"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g58"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g60"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g62"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g64"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g66"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g68"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g70"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
<g
|
||||
id="g72"
|
||||
transform="translate(-12.275,-39.769)">
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 12 KiB |
78
web/pw-frontend/public/static/res/assets/ship.svg
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="100mm"
|
||||
height="100mm"
|
||||
viewBox="0 0 100 99.999999"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="ship.svg"
|
||||
inkscape:version="0.92.4 (f8dce91, 2019-08-02)">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.0993438"
|
||||
inkscape:cx="676.08563"
|
||||
inkscape:cy="474.10966"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1417"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
gridtolerance="10">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid894" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(229.05372,-117.27915)">
|
||||
<ellipse
|
||||
ry="79.47506"
|
||||
rx="48.672089"
|
||||
cy="39.779182"
|
||||
cx="439.0813"
|
||||
id="ellipse888"
|
||||
style="opacity:1;fill:#00ffff;fill-opacity:1;stroke:none;stroke-width:6.61458302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:24.99999809;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 800 -448.82031 C 800 -448.82031 640 -342.04689 640 -92.046875 C 640 -16.101728 661.67774 51.924976 695.88672 97.775391 C 640.96482 152.90966 593.39426 234.74166 610 267.95312 C 620.00003 287.95314 720.00001 297.95311 730 287.95312 C 751.8315 266.12161 757.39662 198.03742 758.92773 149.62305 C 772.03579 155.04778 785.80002 157.95312 800 157.95312 C 814.19998 157.95312 827.96422 155.04778 841.07227 149.62305 C 842.60338 198.03742 848.1685 266.12161 870 287.95312 C 879.99999 297.95311 979.99997 287.95314 990 267.95312 C 1006.6057 234.74166 959.03518 152.90966 904.11328 97.775391 C 938.32226 51.924976 959.99999 -16.101728 960 -92.046875 C 960.00002 -342.04689 800 -448.82031 800 -448.82031 z M 800 -352.04688 C 800 -352.04688 908.96486 -279.33252 908.96484 -109.07617 C 908.96484 -15.046189 860.17918 61.179688 800 61.179688 C 739.82082 61.179688 691.03515 -15.046189 691.03516 -109.07617 C 691.03516 -279.33252 800 -352.04687 800 -352.04688 z "
|
||||
transform="matrix(0.26458333,0,0,0.26458333,-229.05372,117.27915)"
|
||||
id="path4600" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
150
web/pw-frontend/public/static/res/assets/uranus.svg
Normal file
|
@ -0,0 +1,150 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 272.04324 272.17001"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="uranus-with-satellite.svg"
|
||||
inkscape:version="0.92.1 r15371"
|
||||
width="272.04324"
|
||||
height="272.17001"><metadata
|
||||
id="metadata61"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs59" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1536"
|
||||
inkscape:window-height="801"
|
||||
id="namedview57"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.69664401"
|
||||
inkscape:cx="-68.159453"
|
||||
inkscape:cy="136.0855"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Capa_1" />
|
||||
<g
|
||||
id="g24"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
<path
|
||||
d="M 298.973,73.157 C 273.271,47.454 239.096,33.299 202.746,33.299 c -36.35,0 -70.523,14.155 -96.227,39.858 -53.06,53.06 -53.06,139.394 0,192.454 25.703,25.703 59.877,39.858 96.227,39.858 36.35,0 70.524,-14.155 96.227,-39.858 53.059,-53.061 53.059,-139.395 0,-192.454 z m -5.657,186.796 c -11.681,11.681 -25.225,20.819 -39.956,27.156 17.744,-11.698 34.215,-26.208 48.558,-42.92 1.438,-1.676 1.246,-4.202 -0.43,-5.64 -1.678,-1.44 -4.202,-1.247 -5.641,0.43 -20.23,23.57 -48.084,44.664 -75.601,57.302 -5.753,0.781 -11.595,1.188 -17.501,1.188 -4.154,0 -8.276,-0.2 -12.359,-0.589 17.939,-6.343 34.995,-14.887 50.872,-25.52 1.836,-1.229 2.327,-3.714 1.098,-5.549 -1.229,-1.835 -3.712,-2.328 -5.549,-1.098 -19.625,13.143 -41.113,22.987 -63.873,29.279 -5.029,-1.193 -9.966,-2.688 -14.791,-4.477 4.071,-0.974 8.123,-2.079 12.128,-3.313 2.111,-0.651 3.296,-2.89 2.645,-5.001 -0.649,-2.11 -2.89,-3.294 -5,-2.645 -7.405,2.282 -14.973,4.095 -22.518,5.427 -11.638,-5.838 -22.419,-13.502 -31.997,-22.834 4.553,-0.896 9.091,-1.914 13.555,-3.076 2.138,-0.556 3.421,-2.74 2.864,-4.878 -0.555,-2.138 -2.736,-3.42 -4.878,-2.864 -5.959,1.55 -12.05,2.85 -18.137,3.902 C 96.417,242.502 88.55,229.31 83.208,215.361 c 7.844,-2.009 15.644,-4.451 23.246,-7.289 2.069,-0.772 3.121,-3.077 2.348,-5.146 -0.772,-2.069 -3.079,-3.122 -5.146,-2.348 -7.545,2.817 -15.292,5.233 -23.078,7.202 -1.7,-5.44 -3.033,-10.971 -3.992,-16.555 17.341,-5.604 33.99,-13.242 49.518,-22.786 1.882,-1.157 2.47,-3.62 1.313,-5.502 -1.158,-1.881 -3.62,-2.47 -5.503,-1.313 -14.584,8.964 -30.193,16.189 -46.445,21.555 -0.793,-7.386 -0.95,-14.826 -0.465,-22.234 8.314,-3.591 16.365,-7.688 23.955,-12.209 1.897,-1.13 2.521,-3.585 1.39,-5.483 -1.13,-1.898 -3.585,-2.521 -5.483,-1.39 -6.041,3.597 -12.387,6.918 -18.932,9.917 1.118,-8.127 3.015,-16.165 5.69,-23.995 12.924,-7.601 26.339,-17.69 37.186,-27.603 1.631,-1.49 1.745,-4.02 0.255,-5.651 -1.491,-1.632 -4.021,-1.745 -5.651,-0.254 -8.4,7.676 -17.365,14.679 -26.729,20.916 6.137,-13.178 14.632,-25.519 25.492,-36.379 24.192,-24.192 56.357,-37.516 90.57,-37.516 4.656,0 9.271,0.255 13.836,0.743 -1.347,4.072 -2.817,8.13 -4.393,12.113 -0.813,2.054 0.193,4.378 2.248,5.191 0.482,0.191 0.98,0.282 1.471,0.282 1.593,0 3.099,-0.958 3.721,-2.529 1.813,-4.582 3.485,-9.26 5.002,-13.947 5.613,0.961 11.128,2.297 16.52,3.984 -6.004,23.81 -15.831,46.266 -29.255,66.792 -1.209,1.849 -0.69,4.328 1.158,5.537 0.676,0.442 1.435,0.653 2.186,0.653 1.305,0 2.584,-0.638 3.352,-1.811 13.785,-21.077 23.913,-44.115 30.148,-68.536 14.147,5.434 27.287,13.409 38.866,23.679 -2.015,11.874 -5.07,23.73 -9.118,35.272 -0.731,2.084 0.365,4.367 2.45,5.099 0.438,0.154 0.885,0.227 1.324,0.227 1.651,0 3.197,-1.03 3.774,-2.677 3.599,-10.259 6.438,-20.76 8.495,-31.309 16.699,17.153 27.627,37.862 32.781,59.675 -6.798,23.85 -17.03,45.879 -30.438,65.486 -1.247,1.823 -0.779,4.313 1.044,5.56 0.69,0.472 1.477,0.699 2.254,0.699 1.276,0 2.531,-0.61 3.306,-1.743 11.018,-16.112 19.958,-33.794 26.699,-52.727 3.538,36.789 -8.748,74.828 -36.862,102.942 z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0" />
|
||||
|
||||
<path
|
||||
d="m 197.27,216.666 c -1.811,1.267 -2.251,3.761 -0.984,5.571 0.778,1.112 2.02,1.707 3.281,1.707 0.791,0 1.592,-0.235 2.289,-0.723 22.879,-16.008 42.555,-36.287 58.479,-60.273 4.438,-6.686 8.573,-13.669 12.288,-20.754 1.025,-1.957 0.271,-4.375 -1.686,-5.4 -1.952,-1.025 -4.374,-0.272 -5.4,1.685 -3.587,6.843 -7.58,13.587 -11.866,20.044 -15.37,23.149 -34.347,42.711 -56.401,58.143 z"
|
||||
id="path6"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 164.66,235.919 c -4.826,2.292 -9.791,4.417 -14.757,6.314 -2.063,0.789 -3.098,3.101 -2.309,5.164 0.609,1.594 2.127,2.573 3.737,2.573 0.475,0 0.957,-0.085 1.427,-0.265 5.16,-1.972 10.319,-4.179 15.333,-6.561 1.996,-0.948 2.845,-3.334 1.897,-5.329 -0.946,-1.994 -3.333,-2.842 -5.328,-1.896 z"
|
||||
id="path8"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 240.418,146.561 c 1.275,-1.804 0.846,-4.3 -0.958,-5.575 -1.803,-1.275 -4.3,-0.845 -5.575,0.958 -30.046,42.51 -72.305,73.713 -118.993,87.863 -2.114,0.641 -3.309,2.874 -2.668,4.988 0.523,1.728 2.11,2.841 3.826,2.841 0.385,0 0.775,-0.056 1.162,-0.173 48.383,-14.663 92.138,-46.946 123.206,-90.902 z"
|
||||
id="path10"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 131.021,125.104 c 22.662,-18.894 41.814,-42.449 55.387,-68.119 1.032,-1.953 0.286,-4.373 -1.667,-5.406 -1.954,-1.035 -4.373,-0.286 -5.405,1.667 -13.09,24.758 -31.568,47.481 -53.438,65.714 -1.696,1.415 -1.926,3.937 -0.511,5.634 0.791,0.949 1.929,1.438 3.074,1.438 0.903,0 1.811,-0.304 2.56,-0.928 z"
|
||||
id="path12"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 304.583,162.73 c 0.537,0.244 1.1,0.359 1.653,0.359 1.52,0 2.974,-0.872 3.644,-2.346 0.838,-1.843 1.658,-3.714 2.44,-5.563 0.861,-2.034 -0.091,-4.381 -2.125,-5.242 -2.035,-0.861 -4.382,0.09 -5.242,2.125 -0.755,1.784 -1.548,3.59 -2.356,5.37 -0.914,2.012 -0.025,4.383 1.986,5.297 z"
|
||||
id="path14"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 301.081,169.845 c -1.931,-1.072 -4.365,-0.374 -5.438,1.557 -5.468,9.855 -11.719,19.443 -18.58,28.495 -25.229,33.293 -57.633,58.594 -93.705,73.166 -2.049,0.828 -3.038,3.159 -2.211,5.207 0.629,1.558 2.128,2.503 3.71,2.503 0.499,0 1.007,-0.094 1.497,-0.292 37.412,-15.114 70.983,-41.308 97.085,-75.752 7.089,-9.353 13.548,-19.26 19.2,-29.446 1.071,-1.932 0.374,-4.366 -1.558,-5.438 z"
|
||||
id="path16"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 190.943,141.11 c -4.038,4.545 -8.354,8.994 -12.827,13.222 -1.605,1.518 -1.678,4.049 -0.16,5.655 0.787,0.833 1.846,1.252 2.908,1.252 0.985,0 1.974,-0.362 2.746,-1.093 4.643,-4.387 9.122,-9.004 13.313,-13.723 1.468,-1.652 1.318,-4.18 -0.334,-5.647 -1.651,-1.466 -4.179,-1.318 -5.646,0.334 z"
|
||||
id="path18"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 161.323,130.713 c -1.609,1.514 -1.688,4.045 -0.174,5.654 0.787,0.837 1.85,1.26 2.915,1.26 0.982,0 1.967,-0.36 2.739,-1.086 18.801,-17.681 32.125,-35.242 40.733,-53.688 0.934,-2.001 0.068,-4.382 -1.934,-5.316 -2.001,-0.934 -4.382,-0.069 -5.316,1.933 -8.17,17.509 -20.915,34.271 -38.963,51.243 z"
|
||||
id="path20"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 148.218,142.343 c -3.322,2.801 -6.804,5.649 -10.644,8.706 -1.729,1.376 -2.014,3.893 -0.638,5.621 0.789,0.992 1.955,1.508 3.132,1.508 0.873,0 1.752,-0.285 2.488,-0.871 3.899,-3.104 7.438,-5.999 10.817,-8.849 1.689,-1.424 1.904,-3.948 0.479,-5.637 -1.422,-1.687 -3.947,-1.902 -5.634,-0.478 z"
|
||||
id="path22"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
id="g26"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g28"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g30"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g32"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g34"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g36"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g38"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g40"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g42"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g44"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g46"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g48"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g50"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g52"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
<g
|
||||
id="g54"
|
||||
transform="translate(-66.724,-33.299)">
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 8.8 KiB |
114
web/pw-frontend/public/static/res/assets/venus.svg
Normal file
|
@ -0,0 +1,114 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 272.17001 272.17001"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="venus-with-satellite.svg"
|
||||
width="272.17001"
|
||||
height="272.17001"
|
||||
inkscape:version="0.92.1 r15371"><metadata
|
||||
id="metadata43"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs41" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1536"
|
||||
inkscape:window-height="801"
|
||||
id="namedview39"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.72525674"
|
||||
inkscape:cx="-54.610822"
|
||||
inkscape:cy="136.085"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g6" />
|
||||
<g
|
||||
id="g6"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
<path
|
||||
d="m 189.317,26.616 c -75.038,0 -136.085,61.048 -136.085,136.085 0,75.037 61.047,136.085 136.085,136.085 75.038,0 136.085,-61.047 136.085,-136.085 0,-75.038 -61.048,-136.085 -136.085,-136.085 z m 114.537,78.799 c -19.285,81.007 -76.736,147.79 -154.087,179.114 -5.259,-1.711 -10.371,-3.751 -15.309,-6.102 80.857,-31.451 141.937,-101.332 162.187,-185.549 2.629,4.029 5.038,8.214 7.209,12.537 z M 163.18,139.149 c 26.371,-28.772 46.301,-63.476 57.841,-100.56 13.174,3.367 25.536,8.784 36.729,15.887 -19.382,87.483 -83.595,159.155 -168.504,188.074 -8.839,-11.054 -15.885,-23.598 -20.7,-37.19 35.734,-14.765 68.396,-37.583 94.634,-66.211 z M 66.097,197.717 C 64.659,192.664 63.525,187.485 62.714,182.201 125,152.771 174.179,99.363 198.318,34.937 c 5.041,0.352 10.001,0.997 14.865,1.918 -11.221,35.723 -30.474,69.147 -55.901,96.888 -25.304,27.609 -56.763,49.647 -91.185,63.974 z M 189.317,34.616 c 0.192,0 0.382,0.006 0.573,0.007 -23.415,60.543 -69.7,110.809 -128.17,139.196 -0.317,-3.665 -0.488,-7.372 -0.488,-11.118 0,-70.626 57.458,-128.085 128.085,-128.085 z M 94.827,249.08 c 85.048,-30.115 149.458,-102 170.022,-189.755 9.626,7.052 18.236,15.411 25.562,24.818 -18.383,87.024 -81.532,159.278 -165.428,189.276 -11.251,-6.562 -21.416,-14.787 -30.156,-24.339 z m 67.417,38.818 c 71.824,-32.367 125.65,-94.933 146.817,-170.653 4.421,11.608 7.2,24.017 8.052,36.946 -20.52,57.053 -60.724,105.217 -113.336,135.774 -4.748,0.536 -9.571,0.821 -14.46,0.821 -9.287,0 -18.342,-1.002 -27.073,-2.888 z m 63.449,-2.382 c 39.622,-27.44 71.097,-65.121 90.95,-108.895 -5.626,51.82 -42.283,94.456 -90.95,108.895 z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0" />
|
||||
|
||||
</g>
|
||||
<g
|
||||
id="g8"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g10"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g12"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g14"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g16"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g18"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g20"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g22"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g24"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g26"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g28"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g30"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g32"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g34"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
<g
|
||||
id="g36"
|
||||
transform="translate(-53.232,-26.616)">
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.1 KiB |
14
web/pw-frontend/public/static/shaders/frag/image.glsl
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
// Passed in from the vertex shader.
|
||||
varying vec2 v_texCoord;
|
||||
|
||||
// The texture.
|
||||
uniform sampler2D u_texture;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = texture2D(u_texture, v_texCoord);
|
||||
// gl_FragColor = vec4(0.7, 0.7, 0.0, 1.0);
|
||||
}
|
15
web/pw-frontend/public/static/shaders/frag/simple.glsl
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
uniform float u_step_interval;
|
||||
uniform float u_time;
|
||||
uniform vec3 u_color;
|
||||
uniform vec3 u_color_next;
|
||||
|
||||
void main() {
|
||||
|
||||
vec3 color = mix(u_color, u_color_next, u_time);
|
||||
|
||||
gl_FragColor = vec4(color, 1.0);
|
||||
}
|
18
web/pw-frontend/public/static/shaders/frag/vor.glsl
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
#define PI 3.141592
|
||||
|
||||
uniform float u_step_interval;
|
||||
uniform float u_time;
|
||||
uniform bool u_vor;
|
||||
|
||||
varying float v_intensity;
|
||||
varying float v_dist;
|
||||
varying vec3 v_color;
|
||||
varying vec2 v_pos;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vec4(v_color, (1.0 - pow(1.0 - v_intensity, 1.23)) * 0.7);
|
||||
}
|
33
web/pw-frontend/public/static/shaders/vert/image.glsl
Normal file
|
@ -0,0 +1,33 @@
|
|||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
attribute vec2 a_position;
|
||||
attribute vec2 a_texCoord;
|
||||
|
||||
uniform float u_time;
|
||||
|
||||
uniform vec4 u_viewbox; // [x, y, width, height]
|
||||
uniform vec2 u_resolution;
|
||||
uniform mat3 u_trans;
|
||||
|
||||
varying vec2 v_pos;
|
||||
varying vec2 v_texCoord;
|
||||
|
||||
void main() {
|
||||
vec3 pos = vec3(a_position, 1.0);
|
||||
|
||||
pos = u_trans * pos;
|
||||
|
||||
vec2 uv = pos.xy;
|
||||
|
||||
// Viewbox's center is top left, a_position's is in the center to the screen
|
||||
// So translate and scale the viewbox**
|
||||
uv -= u_viewbox.xy + (u_viewbox.zw * 0.5);
|
||||
uv /= u_viewbox.zw * 0.5;
|
||||
|
||||
v_pos = (uv.xy + 1.0) * 0.5;
|
||||
|
||||
gl_Position = vec4(uv.xy, 0.0, 1.0);
|
||||
v_texCoord = a_texCoord;
|
||||
}
|
36
web/pw-frontend/public/static/shaders/vert/simple.glsl
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
attribute vec2 a_position;
|
||||
attribute vec2 a_texCoord;
|
||||
|
||||
uniform float u_time;
|
||||
|
||||
uniform vec4 u_viewbox; // [x, y, width, height]
|
||||
uniform vec2 u_resolution;
|
||||
uniform mat3 u_trans;
|
||||
uniform mat3 u_trans_next;
|
||||
|
||||
varying vec2 v_pos;
|
||||
varying vec2 v_texCoord;
|
||||
|
||||
void main() {
|
||||
vec3 pos = vec3(a_position, 1.0);
|
||||
|
||||
mat3 trans = (u_trans_next * (1.0 - u_time)) + (u_trans * u_time);
|
||||
|
||||
pos = trans * pos;
|
||||
|
||||
vec2 uv = pos.xy;
|
||||
|
||||
// Viewbox's center is top left, a_position's is in the center to the screen
|
||||
// So translate and scale the viewbox**
|
||||
uv -= u_viewbox.xy + (u_viewbox.zw * 0.5);
|
||||
uv /= u_viewbox.zw * 0.5;
|
||||
|
||||
v_pos = (uv.xy + 1.0) * 0.5;
|
||||
|
||||
gl_Position = vec4(uv.xy, 0.0, 1.0);
|
||||
v_texCoord = a_texCoord;
|
||||
}
|
43
web/pw-frontend/public/static/shaders/vert/vor.glsl
Normal file
|
@ -0,0 +1,43 @@
|
|||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
attribute vec2 a_pos;
|
||||
attribute vec2 a_center;
|
||||
attribute float a_own;
|
||||
attribute float a_intensity;
|
||||
|
||||
uniform vec3 u_planet_colours[$PLANETS * 2];
|
||||
uniform vec4 u_viewbox; // [x, y, width, height]
|
||||
uniform vec2 u_resolution;
|
||||
uniform float u_time;
|
||||
|
||||
varying float v_intensity;
|
||||
varying float v_dist;
|
||||
varying vec2 v_pos;
|
||||
varying vec3 v_color;
|
||||
|
||||
void main() {
|
||||
v_intensity = a_intensity;
|
||||
v_dist = distance(a_pos * u_resolution , a_center * u_resolution);
|
||||
|
||||
int own = int(a_own);
|
||||
|
||||
vec2 uv = a_pos;
|
||||
|
||||
// Viewbox's center is top left, a_position's is in the center to the screen
|
||||
// So translate and scale the viewbox**
|
||||
uv -= u_viewbox.xy + (u_viewbox.zw * 0.5);
|
||||
uv /= u_viewbox.zw * 0.5;
|
||||
v_pos = uv.xy;
|
||||
|
||||
// v_pos = (uv.xy + 1.0) * 0.5;
|
||||
|
||||
if (own < 0) {
|
||||
v_color = vec3(0., 0., 0.);
|
||||
} else {
|
||||
v_color = mix(u_planet_colours[own * 2], u_planet_colours[own * 2 + 1], u_time);
|
||||
}
|
||||
|
||||
gl_Position = vec4(uv.xy, 0.0, 1.0);
|
||||
}
|
47
web/pw-frontend/src/App.svelte
Normal file
|
@ -0,0 +1,47 @@
|
|||
<script lang="ts">
|
||||
import Visualizer from './lib/Visualizer.svelte';
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<!-- <img src={logo} alt="Svelte Logo" /> -->
|
||||
<!-- <h1>Hello Typescript!</h1> -->
|
||||
<Visualizer />
|
||||
</main>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
}
|
||||
|
||||
img {
|
||||
height: 16rem;
|
||||
width: 16rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #ff3e00;
|
||||
text-transform: uppercase;
|
||||
font-size: 4rem;
|
||||
font-weight: 100;
|
||||
line-height: 1.1;
|
||||
margin: 2rem auto;
|
||||
max-width: 14rem;
|
||||
}
|
||||
|
||||
p {
|
||||
max-width: 14rem;
|
||||
margin: 1rem auto;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
@media (min-width: 480px) {
|
||||
h1 {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
p {
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
</style>
|
BIN
web/pw-frontend/src/assets/svelte.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
49
web/pw-frontend/src/lib/Visualizer.svelte
Normal file
|
@ -0,0 +1,49 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import * as visualizer from '../lib/visualizer/index';
|
||||
|
||||
onMount(() => {
|
||||
visualizer.init();
|
||||
fetch("match.log")
|
||||
.then(response => response.text())
|
||||
.then(data => visualizer.set_instance(data));
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="main" class="loading">
|
||||
<canvas id="canvas" />
|
||||
<div id="name" />
|
||||
<div id="addbutton" class="button" />
|
||||
|
||||
<div id="meta">
|
||||
<div id="turnCounter">0 / 0</div>
|
||||
<div>
|
||||
<span>Ms per frame: </span>
|
||||
<input type="number" id="speed" value="300" />
|
||||
</div>
|
||||
<div class="slidecontainer">
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="1"
|
||||
value="1"
|
||||
class="slider"
|
||||
id="turnSlider"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lds-roller">
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style scoped>
|
||||
@import 'visualizer/style.css';
|
||||
</style>
|
25
web/pw-frontend/src/lib/visualizer/LICENSE-MIT
Normal file
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2018 Arthur Vercruysse
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
1
web/pw-frontend/src/lib/visualizer/README.md
Normal file
|
@ -0,0 +1 @@
|
|||
Original by the amazing Arthur Vercruysse!
|
102
web/pw-frontend/src/lib/visualizer/index.html
Normal file
|
@ -0,0 +1,102 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Hello wasm-pack!</title>
|
||||
<link rel="stylesheet" type="text/css" href="static/res/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<input type="file" id="fileselect" style="display: none">
|
||||
<div id=wrapper>
|
||||
|
||||
<div id="main" class="loading">
|
||||
<canvas id="c"></canvas>
|
||||
<div id="name"></div>
|
||||
<div id="addbutton" class="button"></div>
|
||||
|
||||
<div id="meta">
|
||||
<div id="turnCounter">
|
||||
0 / 0
|
||||
</div>
|
||||
<div>
|
||||
<span>Ms per frame: </span>
|
||||
<input type="number" id="speed" value="100">
|
||||
</div>
|
||||
<div class="slidecontainer">
|
||||
<input type="range" min="0" max="1" value="1" class="slider" id="turnSlider">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class=".options" id=options>
|
||||
<div class="option">
|
||||
Option one
|
||||
</div>
|
||||
<div class="option">
|
||||
Option two
|
||||
</div>
|
||||
<div class="option">
|
||||
Option three
|
||||
</div>
|
||||
<div class="option">
|
||||
Option three
|
||||
</div>
|
||||
<div class="option">
|
||||
Option three
|
||||
</div>
|
||||
<div class="option">
|
||||
Option three
|
||||
</div>
|
||||
<div class="option">
|
||||
Option three
|
||||
</div>
|
||||
<div class="option">
|
||||
Option three
|
||||
</div>
|
||||
<div class="option">
|
||||
Option three
|
||||
</div>
|
||||
<div class="option">
|
||||
Option three
|
||||
</div><div class="option">
|
||||
Option three
|
||||
</div>
|
||||
<div class="option">
|
||||
Option three
|
||||
</div>
|
||||
<div class="option">
|
||||
Option three
|
||||
</div>
|
||||
<div class="option">
|
||||
Option three
|
||||
</div>
|
||||
<div class="option">
|
||||
Option three
|
||||
</div>
|
||||
<div class="option">
|
||||
Option three
|
||||
</div><div class="option">
|
||||
Option three
|
||||
</div>
|
||||
<div class="option">
|
||||
Option three
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<noscript>This page contains webassembly and javascript content, please enable javascript in your browser.</noscript>
|
||||
<script src="bootstrap.js"></script>
|
||||
<script>
|
||||
const URL = window.location.origin + window.location.pathname;
|
||||
const LOCATION = URL.substring(0, URL.lastIndexOf("/") + 1);
|
||||
|
||||
const game_location = LOCATION + "static/games/Chandra Garrett.json";
|
||||
const name = "Chandra Garrett";
|
||||
window.setTimeout(
|
||||
() => visualizer.handle(game_location, name), 1000
|
||||
)
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
666
web/pw-frontend/src/lib/visualizer/index.ts
Normal file
|
@ -0,0 +1,666 @@
|
|||
import { Game } from "planetwars-rs";
|
||||
// import { memory } from "planetwars-rs/planetwars_rs_bg";
|
||||
// const memory = planetwars_bg.memory;
|
||||
import type { Dictionary } from './webgl/util';
|
||||
import type { BBox } from "./voronoi/voronoi-core";
|
||||
|
||||
import {
|
||||
Resizer,
|
||||
resizeCanvasToDisplaySize,
|
||||
FPSCounter,
|
||||
url_to_mesh,
|
||||
Mesh,
|
||||
} from "./webgl/util";
|
||||
import {
|
||||
Shader,
|
||||
Uniform4f,
|
||||
Uniform3fv,
|
||||
Uniform1f,
|
||||
Uniform2f,
|
||||
ShaderFactory,
|
||||
Uniform3f,
|
||||
UniformMatrix3fv,
|
||||
UniformBool,
|
||||
} from "./webgl/shader";
|
||||
import { Renderer } from "./webgl/renderer";
|
||||
import { VertexBuffer, IndexBuffer } from "./webgl/buffer";
|
||||
import { VertexBufferLayout, VertexArray } from "./webgl/vertexBufferLayout";
|
||||
import { defaultLabelFactory, LabelFactory, Align, Label } from "./webgl/text";
|
||||
import { VoronoiBuilder } from "./voronoi/voronoi";
|
||||
|
||||
// svg-mesh requires global to exist
|
||||
(window as any).global = window;
|
||||
|
||||
|
||||
|
||||
function to_bbox(box: number[]): BBox {
|
||||
return {
|
||||
xl: box[0],
|
||||
xr: box[0] + box[2],
|
||||
yt: box[1],
|
||||
yb: box[1] + box[3],
|
||||
};
|
||||
}
|
||||
|
||||
// function f32v(ptr: number, size: number): Float32Array {
|
||||
// return new Float32Array(memory.buffer, ptr, size);
|
||||
// }
|
||||
|
||||
// function i32v(ptr: number, size: number): Int32Array {
|
||||
// return new Int32Array(memory.buffer, ptr, size);
|
||||
// }
|
||||
|
||||
export function set_game_name(name: string) {
|
||||
ELEMENTS["name"].innerHTML = name;
|
||||
}
|
||||
|
||||
export function set_loading(loading: boolean) {
|
||||
if (loading) {
|
||||
if (!ELEMENTS["main"].classList.contains("loading")) {
|
||||
ELEMENTS["main"].classList.add("loading");
|
||||
}
|
||||
} else {
|
||||
ELEMENTS["main"].classList.remove("loading");
|
||||
}
|
||||
}
|
||||
|
||||
const ELEMENTS: any = {};
|
||||
var CANVAS: any;
|
||||
var RESOLUTION: any;
|
||||
var GL: any;
|
||||
var ms_per_frame: any;
|
||||
|
||||
const LAYERS = {
|
||||
vor: -1, // Background
|
||||
planet: 1,
|
||||
planet_label: 2,
|
||||
ship: 3,
|
||||
ship_label: 4,
|
||||
};
|
||||
|
||||
const COUNTER = new FPSCounter();
|
||||
|
||||
|
||||
|
||||
export function init() {
|
||||
[
|
||||
"name",
|
||||
"turnCounter",
|
||||
"main",
|
||||
"turnSlider",
|
||||
"fileselect",
|
||||
"speed",
|
||||
"canvas",
|
||||
].forEach((n) => (ELEMENTS[n] = document.getElementById(n)));
|
||||
|
||||
CANVAS = ELEMENTS["canvas"];
|
||||
RESOLUTION = [CANVAS.width, CANVAS.height];
|
||||
|
||||
ms_per_frame = parseInt(ELEMENTS["speed"].value);
|
||||
|
||||
GL = CANVAS.getContext("webgl");
|
||||
|
||||
GL.clearColor(0, 0, 0, 1);
|
||||
GL.clear(GL.COLOR_BUFFER_BIT);
|
||||
|
||||
GL.enable(GL.BLEND);
|
||||
GL.blendFunc(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
window.addEventListener(
|
||||
"resize",
|
||||
function () {
|
||||
resizeCanvasToDisplaySize(CANVAS);
|
||||
|
||||
if (game_instance) {
|
||||
game_instance.on_resize();
|
||||
}
|
||||
},
|
||||
{ capture: false, passive: true }
|
||||
);
|
||||
|
||||
ELEMENTS["turnSlider"].oninput = function () {
|
||||
if (game_instance) {
|
||||
game_instance.updateTurn(parseInt(ELEMENTS["turnSlider"].value));
|
||||
}
|
||||
};
|
||||
|
||||
ELEMENTS["speed"].onchange = function () {
|
||||
ms_per_frame = parseInt(ELEMENTS["speed"].value);
|
||||
};
|
||||
}
|
||||
|
||||
export class GameInstance {
|
||||
resizer: Resizer;
|
||||
game: Game;
|
||||
|
||||
shader: Shader;
|
||||
vor_shader: Shader;
|
||||
image_shader: Shader;
|
||||
|
||||
text_factory: LabelFactory;
|
||||
planet_labels: Label[];
|
||||
ship_labels: Label[];
|
||||
|
||||
ship_ibo: IndexBuffer;
|
||||
ship_vao: VertexArray;
|
||||
// TODO: find a better way
|
||||
max_num_ships: number;
|
||||
|
||||
renderer: Renderer;
|
||||
planet_count: number;
|
||||
|
||||
vor_builder: VoronoiBuilder;
|
||||
|
||||
vor_counter = 3;
|
||||
use_vor = true;
|
||||
playing = true;
|
||||
time_stopped_delta = 0;
|
||||
last_time = 0;
|
||||
frame = -1;
|
||||
|
||||
turn_count = 0;
|
||||
|
||||
constructor(
|
||||
game: Game,
|
||||
meshes: Mesh[],
|
||||
ship_mesh: Mesh,
|
||||
shaders: Dictionary<ShaderFactory>
|
||||
) {
|
||||
this.game = game;
|
||||
const planets = game.get_planets();
|
||||
this.planet_count = planets.length;
|
||||
|
||||
this.shader = shaders["normal"].create_shader(GL, {
|
||||
MAX_CIRCLES: "" + planets.length,
|
||||
});
|
||||
this.image_shader = shaders["image"].create_shader(GL);
|
||||
this.vor_shader = shaders["vor"].create_shader(GL, {
|
||||
PLANETS: "" + planets.length,
|
||||
});
|
||||
|
||||
this.text_factory = defaultLabelFactory(GL, this.image_shader);
|
||||
this.planet_labels = [];
|
||||
this.ship_labels = [];
|
||||
|
||||
this.resizer = new Resizer(CANVAS, [...game.get_viewbox()], true);
|
||||
this.renderer = new Renderer();
|
||||
this.game.update_turn(0);
|
||||
|
||||
// Setup key handling
|
||||
document.addEventListener("keydown", this.handleKey.bind(this));
|
||||
|
||||
// List of [(x, y, r)] for all planets
|
||||
this._create_voronoi(planets);
|
||||
this._create_planets(planets, meshes);
|
||||
|
||||
// create_shipes
|
||||
this.ship_ibo = new IndexBuffer(GL, ship_mesh.cells);
|
||||
const ship_positions = new VertexBuffer(GL, ship_mesh.positions);
|
||||
const ship_layout = new VertexBufferLayout();
|
||||
ship_layout.push(GL.FLOAT, 3, 4, "a_position");
|
||||
this.ship_vao = new VertexArray();
|
||||
this.ship_vao.addBuffer(ship_positions, ship_layout);
|
||||
this.max_num_ships = 0;
|
||||
|
||||
// Set slider correctly
|
||||
this.turn_count = game.turn_count();
|
||||
ELEMENTS["turnSlider"].max = this.turn_count - 1 + "";
|
||||
}
|
||||
|
||||
push_state(state: string) {
|
||||
this.game.push_state(state);
|
||||
|
||||
if (this.frame == this.turn_count - 1) {
|
||||
this.playing = true;
|
||||
}
|
||||
|
||||
// Set slider correctly
|
||||
this.turn_count = this.game.turn_count();
|
||||
this.updateTurnCounters();
|
||||
}
|
||||
|
||||
_create_voronoi(planets: Float32Array) {
|
||||
const planet_points = [];
|
||||
for (let i = 0; i < planets.length; i += 3) {
|
||||
planet_points.push({ x: -planets[i], y: -planets[i + 1] });
|
||||
}
|
||||
|
||||
const bbox = to_bbox(this.resizer.get_viewbox());
|
||||
|
||||
this.vor_builder = new VoronoiBuilder(
|
||||
GL,
|
||||
this.vor_shader,
|
||||
planet_points,
|
||||
bbox
|
||||
);
|
||||
this.renderer.addRenderable(this.vor_builder.getRenderable(), LAYERS.vor);
|
||||
}
|
||||
|
||||
_create_planets(planets: Float32Array, meshes: Mesh[]) {
|
||||
for (let i = 0; i < this.planet_count; i++) {
|
||||
{
|
||||
const transform = new UniformMatrix3fv([
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
-planets[i * 3],
|
||||
-planets[i * 3 + 1],
|
||||
1,
|
||||
]);
|
||||
|
||||
const indexBuffer = new IndexBuffer(
|
||||
GL,
|
||||
meshes[i % meshes.length].cells
|
||||
);
|
||||
const positionBuffer = new VertexBuffer(
|
||||
GL,
|
||||
meshes[i % meshes.length].positions
|
||||
);
|
||||
|
||||
const layout = new VertexBufferLayout();
|
||||
layout.push(GL.FLOAT, 3, 4, "a_position");
|
||||
const vao = new VertexArray();
|
||||
vao.addBuffer(positionBuffer, layout);
|
||||
|
||||
this.renderer.addToDraw(
|
||||
indexBuffer,
|
||||
vao,
|
||||
this.shader,
|
||||
{
|
||||
u_trans: transform,
|
||||
u_trans_next: transform,
|
||||
},
|
||||
[],
|
||||
LAYERS.planet
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
const transform = new UniformMatrix3fv([
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
-planets[i * 3],
|
||||
-planets[i * 3 + 1] - 1.2,
|
||||
1,
|
||||
]);
|
||||
|
||||
const label = this.text_factory.build(GL, transform);
|
||||
this.planet_labels.push(label);
|
||||
this.renderer.addRenderable(label.getRenderable(), LAYERS.planet_label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
on_resize() {
|
||||
this.resizer = new Resizer(CANVAS, [...this.game.get_viewbox()], true);
|
||||
const bbox = to_bbox(this.resizer.get_viewbox());
|
||||
this.vor_builder.resize(GL, bbox);
|
||||
}
|
||||
|
||||
_update_state() {
|
||||
this._update_planets();
|
||||
this._update_ships();
|
||||
}
|
||||
|
||||
_update_planets() {
|
||||
const colours = this.game.get_planet_colors();
|
||||
const planet_ships = this.game.get_planet_ships();
|
||||
|
||||
this.vor_shader.uniform(GL, "u_planet_colours", new Uniform3fv(colours));
|
||||
|
||||
for (let i = 0; i < this.planet_count; i++) {
|
||||
const u = new Uniform3f(
|
||||
colours[i * 6],
|
||||
colours[i * 6 + 1],
|
||||
colours[i * 6 + 2]
|
||||
);
|
||||
this.renderer.updateUniform(
|
||||
i,
|
||||
(us) => (us["u_color"] = u),
|
||||
LAYERS.planet
|
||||
);
|
||||
const u2 = new Uniform3f(
|
||||
colours[i * 6 + 3],
|
||||
colours[i * 6 + 4],
|
||||
colours[i * 6 + 5]
|
||||
);
|
||||
this.renderer.updateUniform(
|
||||
i,
|
||||
(us) => (us["u_color_next"] = u2),
|
||||
LAYERS.planet
|
||||
);
|
||||
|
||||
this.planet_labels[i].setText(
|
||||
GL,
|
||||
"*" + planet_ships[i],
|
||||
Align.Middle,
|
||||
Align.Begin
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
_update_ships() {
|
||||
const ships = this.game.get_ship_locations();
|
||||
const labels = this.game.get_ship_label_locations();
|
||||
const ship_counts = this.game.get_ship_counts();
|
||||
const ship_colours = this.game.get_ship_colours();
|
||||
|
||||
for (let i = this.max_num_ships; i < ship_counts.length; i++) {
|
||||
this.renderer.addToDraw(
|
||||
this.ship_ibo,
|
||||
this.ship_vao,
|
||||
this.shader,
|
||||
{},
|
||||
[],
|
||||
LAYERS.ship
|
||||
);
|
||||
|
||||
const label = this.text_factory.build(GL);
|
||||
this.ship_labels.push(label);
|
||||
this.renderer.addRenderable(label.getRenderable(), LAYERS.ship_label);
|
||||
}
|
||||
if (ship_counts.length > this.max_num_ships)
|
||||
this.max_num_ships = ship_counts.length;
|
||||
|
||||
// TODO: actually remove obsolete ships
|
||||
for (let i = 0; i < this.max_num_ships; i++) {
|
||||
if (i < ship_counts.length) {
|
||||
this.ship_labels[i].setText(
|
||||
GL,
|
||||
"" + ship_counts[i],
|
||||
Align.Middle,
|
||||
Align.Middle
|
||||
);
|
||||
|
||||
this.renderer.enableRenderable(i, LAYERS.ship);
|
||||
this.renderer.enableRenderable(i, LAYERS.ship_label);
|
||||
|
||||
const u = new Uniform3f(
|
||||
ship_colours[i * 3],
|
||||
ship_colours[i * 3 + 1],
|
||||
ship_colours[i * 3 + 2]
|
||||
);
|
||||
|
||||
const t1 = new UniformMatrix3fv(ships.slice(i * 18, i * 18 + 9));
|
||||
const t2 = new UniformMatrix3fv(ships.slice(i * 18 + 9, i * 18 + 18));
|
||||
|
||||
const tl1 = new UniformMatrix3fv(labels.slice(i * 18, i * 18 + 9));
|
||||
const tl2 = new UniformMatrix3fv(labels.slice(i * 18 + 9, i * 18 + 18));
|
||||
|
||||
this.renderer.updateUniform(
|
||||
i,
|
||||
(us) => {
|
||||
us["u_color"] = u;
|
||||
us["u_color_next"] = u;
|
||||
us["u_trans"] = t1;
|
||||
us["u_trans_next"] = t2;
|
||||
},
|
||||
LAYERS.ship
|
||||
);
|
||||
|
||||
this.renderer.updateUniform(
|
||||
i,
|
||||
(us) => {
|
||||
us["u_trans"] = tl1;
|
||||
us["u_trans_next"] = tl2;
|
||||
},
|
||||
LAYERS.ship_label
|
||||
);
|
||||
} else {
|
||||
this.renderer.disableRenderable(i, LAYERS.ship);
|
||||
this.renderer.disableRenderable(i, LAYERS.ship_label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render(time: number) {
|
||||
COUNTER.frame(time);
|
||||
|
||||
if (COUNTER.delta(time) < 30) {
|
||||
this.vor_counter = Math.min(3, this.vor_counter + 1);
|
||||
} else {
|
||||
this.vor_counter = Math.max(-3, this.vor_counter - 1);
|
||||
}
|
||||
|
||||
if (this.vor_counter < -2) {
|
||||
this.use_vor = false;
|
||||
}
|
||||
|
||||
// If not playing, still reder with different viewbox, so people can still pan etc.
|
||||
if (!this.playing) {
|
||||
this.last_time = time;
|
||||
|
||||
this.shader.uniform(
|
||||
GL,
|
||||
"u_viewbox",
|
||||
new Uniform4f(this.resizer.get_viewbox())
|
||||
);
|
||||
this.vor_shader.uniform(
|
||||
GL,
|
||||
"u_viewbox",
|
||||
new Uniform4f(this.resizer.get_viewbox())
|
||||
);
|
||||
this.image_shader.uniform(
|
||||
GL,
|
||||
"u_viewbox",
|
||||
new Uniform4f(this.resizer.get_viewbox())
|
||||
);
|
||||
|
||||
this.renderer.render(GL);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if turn is still correct
|
||||
if (time > this.last_time + ms_per_frame) {
|
||||
this.last_time = time;
|
||||
this.updateTurn(this.frame + 1);
|
||||
if (this.frame == this.turn_count - 1) {
|
||||
this.playing = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Do GL things
|
||||
GL.bindFramebuffer(GL.FRAMEBUFFER, null);
|
||||
GL.viewport(0, 0, GL.canvas.width, GL.canvas.height);
|
||||
GL.clear(GL.COLOR_BUFFER_BIT | GL.DEPTH_BUFFER_BIT);
|
||||
|
||||
this.vor_shader.uniform(
|
||||
GL,
|
||||
"u_time",
|
||||
new Uniform1f((time - this.last_time) / ms_per_frame)
|
||||
);
|
||||
this.vor_shader.uniform(
|
||||
GL,
|
||||
"u_viewbox",
|
||||
new Uniform4f(this.resizer.get_viewbox())
|
||||
);
|
||||
this.vor_shader.uniform(GL, "u_resolution", new Uniform2f(RESOLUTION));
|
||||
this.vor_shader.uniform(GL, "u_vor", new UniformBool(this.use_vor));
|
||||
|
||||
this.shader.uniform(
|
||||
GL,
|
||||
"u_time",
|
||||
new Uniform1f((time - this.last_time) / ms_per_frame)
|
||||
);
|
||||
this.shader.uniform(
|
||||
GL,
|
||||
"u_mouse",
|
||||
new Uniform2f(this.resizer.get_mouse_pos())
|
||||
);
|
||||
this.shader.uniform(
|
||||
GL,
|
||||
"u_viewbox",
|
||||
new Uniform4f(this.resizer.get_viewbox())
|
||||
);
|
||||
this.shader.uniform(GL, "u_resolution", new Uniform2f(RESOLUTION));
|
||||
|
||||
this.image_shader.uniform(
|
||||
GL,
|
||||
"u_time",
|
||||
new Uniform1f((time - this.last_time) / ms_per_frame)
|
||||
);
|
||||
this.image_shader.uniform(
|
||||
GL,
|
||||
"u_mouse",
|
||||
new Uniform2f(this.resizer.get_mouse_pos())
|
||||
);
|
||||
this.image_shader.uniform(
|
||||
GL,
|
||||
"u_viewbox",
|
||||
new Uniform4f(this.resizer.get_viewbox())
|
||||
);
|
||||
this.image_shader.uniform(GL, "u_resolution", new Uniform2f(RESOLUTION));
|
||||
|
||||
// Render
|
||||
this.renderer.render(GL);
|
||||
|
||||
COUNTER.frame_end();
|
||||
}
|
||||
|
||||
updateTurn(turn: number) {
|
||||
this.frame = Math.max(0, turn);
|
||||
const new_frame = this.game.update_turn(this.frame);
|
||||
if (new_frame < this.frame) {
|
||||
this.frame = new_frame;
|
||||
this.playing = false;
|
||||
} else {
|
||||
this._update_state();
|
||||
this.playing = true;
|
||||
}
|
||||
|
||||
this.updateTurnCounters();
|
||||
}
|
||||
|
||||
updateTurnCounters() {
|
||||
ELEMENTS["turnCounter"].innerHTML =
|
||||
this.frame + " / " + (this.turn_count - 1);
|
||||
ELEMENTS["turnSlider"].value = this.frame + "";
|
||||
ELEMENTS["turnSlider"].max = this.turn_count - 1 + "";
|
||||
}
|
||||
|
||||
handleKey(event: KeyboardEvent) {
|
||||
// Space
|
||||
if (event.keyCode == 32) {
|
||||
if (this.playing) {
|
||||
this.playing = false;
|
||||
} else {
|
||||
this.playing = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Arrow left
|
||||
if (event.keyCode == 37) {
|
||||
// This feels more natural than -1 what it should be, I think
|
||||
this.updateTurn(this.frame - 2);
|
||||
}
|
||||
|
||||
// Arrow right
|
||||
if (event.keyCode == 39) {
|
||||
this.updateTurn(this.frame + 1);
|
||||
}
|
||||
|
||||
// d key
|
||||
if (event.keyCode == 68) {
|
||||
ELEMENTS["speed"].value = ms_per_frame + 10 + "";
|
||||
ELEMENTS["speed"].onchange(undefined);
|
||||
}
|
||||
|
||||
// a key
|
||||
if (event.keyCode == 65) {
|
||||
ELEMENTS["speed"].value = Math.max(ms_per_frame - 10, 0) + "";
|
||||
ELEMENTS["speed"].onchange(undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var game_instance: GameInstance;
|
||||
var meshes: Mesh[];
|
||||
var shaders: Dictionary<ShaderFactory>;
|
||||
|
||||
export async function set_instance(source: string): Promise<GameInstance> {
|
||||
if (!meshes || !shaders) {
|
||||
const mesh_promises = ["ship.svg", "earth.svg", "mars.svg", "venus.svg"]
|
||||
.map((name) => "/static/res/assets/" + name)
|
||||
.map(url_to_mesh);
|
||||
|
||||
const shader_promies = [
|
||||
(async () =>
|
||||
<[string, ShaderFactory]>[
|
||||
"normal",
|
||||
await ShaderFactory.create_factory(
|
||||
"/static/shaders/frag/simple.glsl",
|
||||
"/static/shaders/vert/simple.glsl"
|
||||
),
|
||||
])(),
|
||||
(async () =>
|
||||
<[string, ShaderFactory]>[
|
||||
"vor",
|
||||
await ShaderFactory.create_factory(
|
||||
"/static/shaders/frag/vor.glsl",
|
||||
"/static/shaders/vert/vor.glsl"
|
||||
),
|
||||
])(),
|
||||
(async () =>
|
||||
<[string, ShaderFactory]>[
|
||||
"image",
|
||||
await ShaderFactory.create_factory(
|
||||
"/static/shaders/frag/image.glsl",
|
||||
"/static/shaders/vert/simple.glsl"
|
||||
),
|
||||
])(),
|
||||
];
|
||||
let shaders_array: [string, ShaderFactory][];
|
||||
[meshes, shaders_array] = await Promise.all([
|
||||
Promise.all(mesh_promises),
|
||||
Promise.all(shader_promies),
|
||||
]);
|
||||
|
||||
shaders = {};
|
||||
shaders_array.forEach(([name, fac]) => (shaders[name] = fac));
|
||||
}
|
||||
|
||||
resizeCanvasToDisplaySize(CANVAS);
|
||||
|
||||
game_instance = new GameInstance(
|
||||
Game.new(source),
|
||||
meshes.slice(1),
|
||||
meshes[0],
|
||||
shaders
|
||||
);
|
||||
|
||||
set_loading(false);
|
||||
start();
|
||||
return game_instance;
|
||||
}
|
||||
|
||||
var _animating = false;
|
||||
|
||||
export function start() {
|
||||
if (_animating) {
|
||||
// already running
|
||||
return;
|
||||
}
|
||||
_animating = true;
|
||||
requestAnimationFrame(step);
|
||||
}
|
||||
|
||||
export function stop() {
|
||||
_animating = false;
|
||||
}
|
||||
|
||||
function step(time: number) {
|
||||
if (game_instance) {
|
||||
game_instance.render(time);
|
||||
}
|
||||
|
||||
if (_animating) {
|
||||
requestAnimationFrame(step);
|
||||
}
|
||||
}
|
47
web/pw-frontend/src/lib/visualizer/src/games.ts
Normal file
|
@ -0,0 +1,47 @@
|
|||
|
||||
import { set_game_name, set_loading, set_instance } from '../index'
|
||||
|
||||
var game_name, game_file;
|
||||
|
||||
document.getElementById("addbutton").onclick = function () {
|
||||
const loc = window.location;
|
||||
const query = `?game=${game_file}&name=${game_name}`;
|
||||
navigator.clipboard.writeText(loc.origin + loc.pathname + encodeURI(query)).then(() => {
|
||||
console.log("Success");
|
||||
}, () => {
|
||||
console.log("Failed");
|
||||
});
|
||||
}
|
||||
|
||||
async function on_load() {
|
||||
const options = document.getElementsByClassName("options");
|
||||
const urlVars = new URLSearchParams(window.location.search);
|
||||
|
||||
if (urlVars.get("game") && urlVars.get("name")) {
|
||||
console.log(urlVars.get("game") + ' ' + urlVars.get("name"))
|
||||
handle(urlVars.get("game"), urlVars.get("name"))
|
||||
} else if (options[0]) {
|
||||
const options_div = <HTMLDivElement>options[0];
|
||||
if (options_div.children[0]) {
|
||||
options_div.children[0].dispatchEvent(new Event('click'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("load", on_load, false);
|
||||
|
||||
export function handle(location: string, name: string) {
|
||||
game_file = location;
|
||||
game_name = name;
|
||||
|
||||
set_loading(true);
|
||||
|
||||
fetch(location)
|
||||
.then((r) => r.text())
|
||||
.then((response) => {
|
||||
set_instance(response);
|
||||
set_game_name(name);
|
||||
}).catch(console.error);
|
||||
}
|
||||
|
||||
on_load();
|
309
web/pw-frontend/src/lib/visualizer/style.css
Normal file
|
@ -0,0 +1,309 @@
|
|||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
p {
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
max-height: 100%;
|
||||
min-height: 100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#main {
|
||||
height: 100%;
|
||||
flex-grow: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#name {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#meta {
|
||||
padding: 10px 2%;
|
||||
color: white;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 96%;
|
||||
}
|
||||
|
||||
.options {
|
||||
background-color: black;
|
||||
max-width: 300px;
|
||||
width: 20%;
|
||||
min-width: 150px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.option {
|
||||
color: white;
|
||||
margin: 0 0 20px 0;
|
||||
padding: 10px;
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.option:last-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.option:hover {
|
||||
background-color: #777;
|
||||
}
|
||||
|
||||
.lds-roller {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.loading>.lds-roller {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.lds-roller {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.lds-roller div {
|
||||
animation: lds-roller 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
||||
transform-origin: 40px 40px;
|
||||
}
|
||||
|
||||
.lds-roller div:after {
|
||||
content: " ";
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
margin: -4px 0 0 -4px;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(1) {
|
||||
animation-delay: -0.036s;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(1):after {
|
||||
top: 63px;
|
||||
left: 63px;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(2) {
|
||||
animation-delay: -0.072s;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(2):after {
|
||||
top: 68px;
|
||||
left: 56px;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(3) {
|
||||
animation-delay: -0.108s;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(3):after {
|
||||
top: 71px;
|
||||
left: 48px;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(4) {
|
||||
animation-delay: -0.144s;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(4):after {
|
||||
top: 72px;
|
||||
left: 40px;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(5) {
|
||||
animation-delay: -0.18s;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(5):after {
|
||||
top: 71px;
|
||||
left: 32px;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(6) {
|
||||
animation-delay: -0.216s;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(6):after {
|
||||
top: 68px;
|
||||
left: 24px;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(7) {
|
||||
animation-delay: -0.252s;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(7):after {
|
||||
top: 63px;
|
||||
left: 17px;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(8) {
|
||||
animation-delay: -0.288s;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(8):after {
|
||||
top: 56px;
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
@keyframes lds-roller {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
#speed {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
#canvas {
|
||||
position: relative;
|
||||
background-color: black;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.button {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.button::before {
|
||||
content: "";
|
||||
display: block;
|
||||
float: left;
|
||||
margin: 0 -20px 0 0;
|
||||
font-family: 'fontawesome';
|
||||
content: "\f1e1";
|
||||
transform: translate(-1em, 0px);
|
||||
color: antiquewhite;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.button:hover::before {
|
||||
color: #ff7f00;
|
||||
}
|
||||
/* ----------------------------------------------
|
||||
* Generated by Animista on 2019-9-17 14:35:13
|
||||
* Licensed under FreeBSD License.
|
||||
* See http://animista.net/license for more info.
|
||||
* w: http://animista.net, t: @cssanimista
|
||||
* ---------------------------------------------- */
|
||||
/**
|
||||
* ----------------------------------------
|
||||
* animation slide-top
|
||||
* ----------------------------------------
|
||||
*/
|
||||
|
||||
@-webkit-keyframes slide-top {
|
||||
0% {
|
||||
-webkit-transform: translate(-50%, 50%);
|
||||
transform: translate(-50%, 50%);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: translate(-50%, -150%);
|
||||
transform: translate(-50%, -150%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-top {
|
||||
0% {
|
||||
-webkit-transform: translate(-50%, 50%);
|
||||
transform: translate(-50%, 50%);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: translate(-50%, -150%);
|
||||
transform: translate(-50%, -150%);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ----------------------------------------
|
||||
* Copy from https://www.w3schools.com/howto/howto_js_rangeslider.asp
|
||||
* ----------------------------------------
|
||||
*/
|
||||
|
||||
.slidecontainer {
|
||||
margin-top: 10px;
|
||||
width: 100%;
|
||||
/* Width of the outside container */
|
||||
}
|
||||
|
||||
.slider {
|
||||
-webkit-appearance: none;
|
||||
width: 100%;
|
||||
height: 15px;
|
||||
border-radius: 5px;
|
||||
background: #d3d3d3;
|
||||
outline: none;
|
||||
opacity: 0.7;
|
||||
-webkit-transition: .2s;
|
||||
transition: opacity .2s;
|
||||
}
|
||||
|
||||
.slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
border-radius: 50%;
|
||||
background: #ff7000;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.slider::-moz-range-thumb {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
border-radius: 50%;
|
||||
background: #ff7000;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
|
||||
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
|
||||
border-radius: 10px;
|
||||
background-color: #444;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background-color: #F90;
|
||||
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .2) 50%, rgba(255, 255, 255, .2) 75%, transparent 75%, transparent)
|
||||
}
|
56
web/pw-frontend/src/lib/visualizer/voronoi/voronoi-core.d.ts
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
|
||||
declare namespace Voronoi {
|
||||
class Point {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
class Site {
|
||||
x: number;
|
||||
y: number;
|
||||
voronoiId: number;
|
||||
}
|
||||
|
||||
class Cell {
|
||||
site: Site;
|
||||
halfedges: HalfEdge[];
|
||||
closeMe: boolean;
|
||||
}
|
||||
|
||||
class Edge {
|
||||
lSite: Site;
|
||||
rSite: Site;
|
||||
vb: Point;
|
||||
va: Point;
|
||||
}
|
||||
|
||||
class HalfEdge {
|
||||
site: Site;
|
||||
edge: Edge;
|
||||
angle: number;
|
||||
getStartpoint(): Point;
|
||||
getEndpoint(): Point;
|
||||
}
|
||||
|
||||
class BBox {
|
||||
xl: number;
|
||||
xr: number;
|
||||
yt: number;
|
||||
yb: number;
|
||||
}
|
||||
|
||||
class VoronoiDiagram {
|
||||
site: any;
|
||||
cells: Cell[];
|
||||
edges: Edge[];
|
||||
vertices: Point[];
|
||||
execTime: number;
|
||||
}
|
||||
}
|
||||
|
||||
declare class Voronoi {
|
||||
constructor();
|
||||
compute(sites: Voronoi.Point[], bbox: Voronoi.BBox): Voronoi.VoronoiDiagram;
|
||||
}
|
||||
|
||||
export = Voronoi;
|
1726
web/pw-frontend/src/lib/visualizer/voronoi/voronoi-core.js
Normal file
165
web/pw-frontend/src/lib/visualizer/voronoi/voronoi.ts
Normal file
|
@ -0,0 +1,165 @@
|
|||
import type { Shader } from "../webgl/shader";
|
||||
import type { BBox, Point } from "./voronoi-core";
|
||||
import Voronoi from "./voronoi-core";
|
||||
import { DefaultRenderable } from "../webgl/renderer";
|
||||
import { IndexBuffer, VertexBuffer } from "../webgl/buffer";
|
||||
import { VertexBufferLayout, VertexArray } from "../webgl/vertexBufferLayout";
|
||||
|
||||
function arcctg(x: number): number { return Math.PI / 2 - Math.atan(x); }
|
||||
|
||||
function to_key(p: Point): string {
|
||||
return [p.x, p.y] + "";
|
||||
}
|
||||
|
||||
function round_point(center: Point, point: Point, amount_fn = (b: number) => 0.7): Point {
|
||||
const d = dist(center, point, true);
|
||||
const x = center.x + amount_fn(d) * (point.x - center.x);
|
||||
const y = center.y + amount_fn(d) * (point.y - center.y);
|
||||
return { 'x': x, 'y': y };
|
||||
}
|
||||
|
||||
function median_point(c: Point, p: Point, n: Point, d = 0.1): number[] {
|
||||
const dd = 1.0 - 2 * d;
|
||||
return [
|
||||
dd * c.x + d * p.x + d * n.x,
|
||||
dd * c.y + d * p.y + d * n.y,
|
||||
]
|
||||
}
|
||||
|
||||
function build_point_map(es: Voronoi.HalfEdge[]): (point: Point) => Point {
|
||||
const mean = es.map(e => dist(e.getStartpoint(), e.getEndpoint())).reduce((a, b) => a + b, 0) / es.length;
|
||||
const map = {};
|
||||
|
||||
for (let edge of es) {
|
||||
const start = edge.getStartpoint();
|
||||
const end = edge.getEndpoint();
|
||||
|
||||
if (dist(start, end) < 0.03 * mean) { // These points have to be merged
|
||||
const middle = { 'x': (start.x + end.x) / 2, 'y': (start.y + end.y) / 2 };
|
||||
map[to_key(start)] = middle;
|
||||
map[to_key(end)] = middle;
|
||||
}
|
||||
}
|
||||
|
||||
return (p) => map[to_key(p)] || p;
|
||||
}
|
||||
|
||||
function get_round_fn(dist_mean: number, amount = 0.7): (d: number) => number {
|
||||
return (d) => arcctg((d - dist_mean) / dist_mean) / Math.PI + 0.6;
|
||||
}
|
||||
|
||||
function dist(a: Point, b: Point, norm = false): number {
|
||||
const dx = a.x - b.x;
|
||||
const dy = a.y - b.y;
|
||||
if (norm) return Math.sqrt(dx * dx + dy * dy);
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
|
||||
export class VoronoiBuilder {
|
||||
inner: DefaultRenderable;
|
||||
|
||||
vor: Voronoi;
|
||||
planets: Point[];
|
||||
|
||||
|
||||
constructor(gl: WebGLRenderingContext, shader: Shader, planets: Point[], bbox: BBox) {
|
||||
this.vor = new Voronoi();
|
||||
this.planets = planets;
|
||||
|
||||
const ib = new IndexBuffer(gl, []);
|
||||
const vb = new VertexBuffer(gl, []);
|
||||
|
||||
const layout = new VertexBufferLayout();
|
||||
layout.push(gl.FLOAT, 2, 4, "a_pos");
|
||||
layout.push(gl.FLOAT, 2, 4, "a_center");
|
||||
layout.push(gl.FLOAT, 1, 4, "a_own");
|
||||
layout.push(gl.FLOAT, 1, 4, "a_intensity");
|
||||
|
||||
const vao = new VertexArray();
|
||||
vao.addBuffer(vb, layout);
|
||||
|
||||
this.inner = new DefaultRenderable(ib, vao, shader, [], {});
|
||||
|
||||
this.resize(gl, bbox);
|
||||
}
|
||||
|
||||
getRenderable(): DefaultRenderable {
|
||||
return this.inner;
|
||||
}
|
||||
|
||||
resize(gl: WebGLRenderingContext, bbox: BBox) {
|
||||
const start = new Date().getTime();
|
||||
|
||||
// This voronoi sorts the planets, then owners don't align anymore
|
||||
const own_map = {};
|
||||
this.planets.forEach((p, i) => own_map[to_key(p)] = i);
|
||||
|
||||
const vor = this.vor.compute(this.planets, bbox);
|
||||
|
||||
const attrs = [];
|
||||
const ids = [];
|
||||
|
||||
let vertCount = 0;
|
||||
|
||||
for (let i = 0; i < vor.cells.length; i++) {
|
||||
const cell = vor.cells[i];
|
||||
const planetId = own_map[to_key(cell.site)];
|
||||
const point_map = build_point_map(cell.halfedges);
|
||||
|
||||
const centerId = vertCount++;
|
||||
|
||||
attrs.push(cell.site.x, cell.site.y);
|
||||
attrs.push(cell.site.x, cell.site.y);
|
||||
attrs.push(planetId);
|
||||
attrs.push(1);
|
||||
|
||||
const dist_mean = cell.halfedges.map(e => {
|
||||
const start = e.getStartpoint();
|
||||
const end = e.getEndpoint();
|
||||
return dist(cell.site, start, true) + dist(cell.site, { 'x': (start.x + end.x) / 2, 'y': (start.y + end.y) / 2 }, true)
|
||||
}).reduce((a, b) => a + b, 0) / cell.halfedges.length / 2;
|
||||
const round_fn = get_round_fn(dist_mean);
|
||||
|
||||
for (let edge of cell.halfedges) {
|
||||
let start = point_map(edge.getStartpoint());
|
||||
let end = point_map(edge.getEndpoint());
|
||||
let center = { 'x': (start.x + end.x) / 2, 'y': (start.y + end.y) / 2 };
|
||||
|
||||
if (to_key(start) == to_key(end)) continue;
|
||||
|
||||
start = round_point(cell.site, start, round_fn);
|
||||
center = round_point(cell.site, center, round_fn);
|
||||
end = round_point(cell.site, end, round_fn);
|
||||
|
||||
ids.push(centerId);
|
||||
ids.push(vertCount++);
|
||||
attrs.push(start.x, start.y);
|
||||
attrs.push(cell.site.x, cell.site.y);
|
||||
attrs.push(planetId);
|
||||
attrs.push(0);
|
||||
|
||||
ids.push(vertCount++);
|
||||
attrs.push(center.x, center.y);
|
||||
attrs.push(cell.site.x, cell.site.y);
|
||||
attrs.push(planetId);
|
||||
attrs.push(0);
|
||||
|
||||
ids.push(centerId);
|
||||
ids.push(vertCount - 1);
|
||||
|
||||
ids.push(vertCount++);
|
||||
attrs.push(end.x, end.y);
|
||||
attrs.push(cell.site.x, cell.site.y);
|
||||
attrs.push(planetId);
|
||||
attrs.push(0);
|
||||
}
|
||||
}
|
||||
|
||||
this.inner.updateIndexBuffer(gl, ids);
|
||||
this.inner.updateVAOBuffer(gl, 0, attrs);
|
||||
|
||||
console.log(`Vor things took ${new Date().getTime() - start} ms!`)
|
||||
}
|
||||
}
|
||||
|
||||
export default VoronoiBuilder;
|
55
web/pw-frontend/src/lib/visualizer/webgl/buffer.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
|
||||
export class Buffer {
|
||||
buffer: WebGLBuffer;
|
||||
data: any;
|
||||
count: number;
|
||||
type: number;
|
||||
|
||||
constructor(gl: WebGLRenderingContext, data: number[], type: number) {
|
||||
this.buffer = gl.createBuffer();
|
||||
this.type = type;
|
||||
|
||||
if (data)
|
||||
this.updateData(gl, data);
|
||||
}
|
||||
|
||||
_toArray(data: number[]): any {
|
||||
return new Float32Array(data);
|
||||
}
|
||||
|
||||
updateData(gl: WebGLRenderingContext, data: number[]) {
|
||||
this.data = data;
|
||||
this.count = data.length;
|
||||
gl.bindBuffer(this.type, this.buffer);
|
||||
gl.bufferData(this.type, this._toArray(data), gl.STATIC_DRAW);
|
||||
}
|
||||
|
||||
bind(gl: WebGLRenderingContext) {
|
||||
gl.bindBuffer(this.type, this.buffer);
|
||||
}
|
||||
|
||||
getCount(): number {
|
||||
return this.count;
|
||||
}
|
||||
}
|
||||
|
||||
export class VertexBuffer extends Buffer {
|
||||
constructor(gl: WebGLRenderingContext, data: any) {
|
||||
super(gl, data, gl.ARRAY_BUFFER);
|
||||
}
|
||||
|
||||
_toArray(data: number[]): any {
|
||||
return new Float32Array(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class IndexBuffer extends Buffer {
|
||||
constructor(gl: WebGLRenderingContext, data: any) {
|
||||
super(gl, data, gl.ELEMENT_ARRAY_BUFFER);
|
||||
}
|
||||
|
||||
_toArray(data: number[]): any {
|
||||
return new Uint16Array(data);
|
||||
}
|
||||
}
|
122
web/pw-frontend/src/lib/visualizer/webgl/index.ts
Normal file
|
@ -0,0 +1,122 @@
|
|||
import { Uniform4f, Uniform1f, Uniform2f, ShaderFactory, UniformMatrix3fv, Uniform3f } from './shader';
|
||||
import { resizeCanvasToDisplaySize, FPSCounter, onload2promise, Resizer, url_to_mesh } from "./util";
|
||||
import { VertexBuffer, IndexBuffer } from './buffer';
|
||||
import { VertexArray, VertexBufferLayout } from './vertexBufferLayout';
|
||||
import { Renderer } from './renderer';
|
||||
import { Texture } from './texture';
|
||||
|
||||
const URL = window.location.origin+window.location.pathname;
|
||||
const LOCATION = URL.substring(0, URL.lastIndexOf("/") + 1);
|
||||
|
||||
async function create_texture_from_svg(gl: WebGLRenderingContext, name: string, path: string, width: number, height: number): Promise<Texture> {
|
||||
|
||||
const [mesh, factory] = await Promise.all([
|
||||
url_to_mesh(path),
|
||||
ShaderFactory.create_factory(LOCATION + "static/shaders/frag/static_color.glsl", LOCATION + "static/shaders/vert/svg.glsl")
|
||||
]);
|
||||
|
||||
const program = factory.create_shader(gl);
|
||||
const renderer = new Renderer();
|
||||
|
||||
var positionBuffer = new VertexBuffer(gl, mesh.positions);
|
||||
var layout = new VertexBufferLayout();
|
||||
layout.push(gl.FLOAT, 3, 4, "a_position");
|
||||
|
||||
const vao = new VertexArray();
|
||||
vao.addBuffer(positionBuffer, layout);
|
||||
|
||||
program.bind(gl);
|
||||
vao.bind(gl, program);
|
||||
|
||||
var indexBuffer = new IndexBuffer(gl, mesh.cells);
|
||||
indexBuffer.bind(gl);
|
||||
|
||||
renderer.addToDraw(indexBuffer, vao, program, {});
|
||||
|
||||
return Texture.fromRenderer(gl, name, width, height, renderer);
|
||||
}
|
||||
|
||||
|
||||
async function main() {
|
||||
|
||||
// Get A WebGL context
|
||||
var canvas = <HTMLCanvasElement>document.getElementById("c");
|
||||
const resolution = [canvas.width, canvas.height];
|
||||
|
||||
const resizer = new Resizer(canvas, [-10, -10, 20, 20], true);
|
||||
|
||||
var gl = canvas.getContext("webgl");
|
||||
if (!gl) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mesh = await url_to_mesh("static/res/images/earth.svg");
|
||||
console.log(Math.max(...mesh.positions), Math.min(...mesh.positions));
|
||||
const renderer = new Renderer();
|
||||
|
||||
const factory = await ShaderFactory.create_factory(LOCATION + "static/shaders/frag/static_color.glsl", LOCATION + "static/shaders/vert/simple.glsl");
|
||||
const program = factory.create_shader(gl);
|
||||
|
||||
var positionBuffer = new VertexBuffer(gl, mesh.positions);
|
||||
var layout = new VertexBufferLayout();
|
||||
layout.push(gl.FLOAT, 3, 4, "a_position");
|
||||
// layout.push(gl.FLOAT, 2, 4, "a_tex");
|
||||
|
||||
const vao = new VertexArray();
|
||||
vao.addBuffer(positionBuffer, layout);
|
||||
|
||||
resizeCanvasToDisplaySize(<HTMLCanvasElement>gl.canvas);
|
||||
|
||||
// Tell WebGL how to convert from clip space to pixels
|
||||
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
|
||||
|
||||
// Clear the canvas
|
||||
gl.clearColor(0, 0, 0, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
gl.enable(gl.BLEND);
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
program.bind(gl);
|
||||
vao.bind(gl, program);
|
||||
|
||||
var indexBuffer = new IndexBuffer(gl, mesh.cells);
|
||||
indexBuffer.bind(gl);
|
||||
|
||||
renderer.addToDraw(indexBuffer, vao, program, {});
|
||||
|
||||
const counter = new FPSCounter();
|
||||
|
||||
const step = function (time: number) {
|
||||
|
||||
// console.log(resizer.get_viewbox());
|
||||
|
||||
program.uniform(gl, "u_time", new Uniform1f(time * 0.001));
|
||||
program.uniform(gl, "u_mouse", new Uniform2f(resizer.get_mouse_pos()));
|
||||
program.uniform(gl, "u_viewbox", new Uniform4f(resizer.get_viewbox()));
|
||||
program.uniform(gl, "u_resolution", new Uniform2f(resolution));
|
||||
program.uniform(gl, "u_trans", new UniformMatrix3fv([1, 0, 0, 0, 1, 0, 0, 0, 1]));
|
||||
program.uniform(gl, "u_color", new Uniform3f(1.0, 0.5, 0.0));
|
||||
|
||||
renderer.render(gl);
|
||||
|
||||
counter.frame(time);
|
||||
requestAnimationFrame(step);
|
||||
}
|
||||
|
||||
requestAnimationFrame(step);
|
||||
}
|
||||
|
||||
|
||||
main();
|
||||
|
||||
document.getElementById("loader").classList.remove("loading");
|
||||
|
||||
// const loader = document.getElementById("loader");
|
||||
// setInterval(() => {
|
||||
// if (loader.classList.contains("loading")) {
|
||||
// loader.classList.remove("loading")
|
||||
// } else {
|
||||
// loader.classList.add("loading");
|
||||
// }
|
||||
// }, 2000);
|
157
web/pw-frontend/src/lib/visualizer/webgl/renderer.ts
Normal file
|
@ -0,0 +1,157 @@
|
|||
import type { IndexBuffer } from './buffer';
|
||||
import type { VertexArray } from './vertexBufferLayout';
|
||||
import type { Texture } from './texture';
|
||||
import type { Dictionary } from './util';
|
||||
import type { Shader, Uniform } from './shader';
|
||||
import { Uniform1i } from './shader';
|
||||
|
||||
function sortedIndex(array, value) {
|
||||
var low = 0,
|
||||
high = array.length;
|
||||
|
||||
while (low < high) {
|
||||
var mid = (low + high) >>> 1;
|
||||
if (array[mid] < value) low = mid + 1;
|
||||
else high = mid;
|
||||
}
|
||||
return low;
|
||||
}
|
||||
|
||||
export interface Renderable {
|
||||
getUniforms() : Dictionary<Uniform>;
|
||||
render(gl: WebGLRenderingContext): void;
|
||||
updateVAOBuffer(gl: WebGLRenderingContext, index: number, data: number[]);
|
||||
updateIndexBuffer(gl: WebGLRenderingContext, data: number[]);
|
||||
}
|
||||
|
||||
export class DefaultRenderable implements Renderable {
|
||||
ibo: IndexBuffer;
|
||||
va: VertexArray;
|
||||
shader: Shader;
|
||||
textures: Texture[];
|
||||
uniforms: Dictionary<Uniform>;
|
||||
|
||||
constructor(
|
||||
ibo: IndexBuffer,
|
||||
va: VertexArray,
|
||||
shader: Shader,
|
||||
textures: Texture[],
|
||||
uniforms: Dictionary<Uniform>,
|
||||
) {
|
||||
this.ibo = ibo;
|
||||
this.va = va;
|
||||
this.shader = shader;
|
||||
this.textures = textures;
|
||||
this.uniforms = uniforms;
|
||||
}
|
||||
|
||||
getUniforms(): Dictionary<Uniform> {
|
||||
return this.uniforms;
|
||||
}
|
||||
|
||||
updateVAOBuffer(gl: WebGLRenderingContext, index: number, data: number[]) {
|
||||
this.va.updateBuffer(gl, index, data);
|
||||
}
|
||||
|
||||
updateIndexBuffer(gl: WebGLRenderingContext, data: number[]) {
|
||||
this.ibo.updateData(gl, data);
|
||||
}
|
||||
|
||||
render(gl: WebGLRenderingContext): void {
|
||||
|
||||
const indexBuffer = this.ibo;
|
||||
const vertexArray = this.va;
|
||||
const uniforms = this.uniforms;
|
||||
|
||||
const shader = this.shader;
|
||||
const textures = this.textures;
|
||||
let texLocation = 0;
|
||||
|
||||
for (let texture of textures) {
|
||||
|
||||
shader.uniform(gl, texture.name, new Uniform1i(texLocation));
|
||||
texture.bind(gl, texLocation);
|
||||
|
||||
texLocation ++;
|
||||
// if (texLocation > maxTextures) {
|
||||
// console.error("Using too many textures, this is not supported yet\nUndefined behaviour!");
|
||||
// }
|
||||
}
|
||||
|
||||
if (vertexArray && shader && uniforms) {
|
||||
for(let key in uniforms) {
|
||||
shader.uniform(gl, key, uniforms[key]);
|
||||
}
|
||||
|
||||
vertexArray.bind(gl, shader);
|
||||
|
||||
if (indexBuffer) {
|
||||
indexBuffer.bind(gl);
|
||||
gl.drawElements(gl.TRIANGLES, indexBuffer.getCount(), gl.UNSIGNED_SHORT, 0);
|
||||
} else {
|
||||
console.error("IndexBuffer is required to render, for now");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export class Renderer {
|
||||
renderables: { [id: number] : [Renderable, boolean][]; };
|
||||
renderable_layers: number[];
|
||||
|
||||
constructor() {
|
||||
this.renderables = {};
|
||||
this.renderable_layers = [];
|
||||
}
|
||||
|
||||
updateUniform(i: number, f: (uniforms: Dictionary<Uniform>) => void, layer=0, ) {
|
||||
f(this.renderables[layer][i][0].getUniforms());
|
||||
}
|
||||
|
||||
disableRenderable(i: number, layer=0) {
|
||||
this.renderables[layer][i][1] = false;
|
||||
}
|
||||
|
||||
enableRenderable(i: number, layer=0) {
|
||||
this.renderables[layer][i][1] = true;
|
||||
}
|
||||
|
||||
addRenderable(item: Renderable, layer=0): number {
|
||||
if(!this.renderables[layer]) {
|
||||
const idx = sortedIndex(this.renderable_layers, layer);
|
||||
this.renderable_layers.splice(idx, 0, layer);
|
||||
this.renderables[layer] = [];
|
||||
}
|
||||
|
||||
this.renderables[layer].push([item, true]);
|
||||
return this.renderables[layer].length - 1;
|
||||
}
|
||||
|
||||
addToDraw(indexBuffer: IndexBuffer, vertexArray: VertexArray, shader: Shader, uniforms?: Dictionary<Uniform>, texture?: Texture[], layer=0): number {
|
||||
return this.addRenderable(
|
||||
new DefaultRenderable(
|
||||
indexBuffer,
|
||||
vertexArray,
|
||||
shader,
|
||||
texture || [],
|
||||
uniforms || {},
|
||||
), layer
|
||||
);
|
||||
}
|
||||
|
||||
render(gl: WebGLRenderingContext, frameBuffer?: WebGLFramebuffer, width?: number, height?: number) {
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
|
||||
gl.viewport(0, 0, width || gl.canvas.width, height || gl.canvas.height);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
|
||||
const maxTextures = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS);
|
||||
|
||||
for (let layer of this.renderable_layers) {
|
||||
for (let [r, e] of this.renderables[layer]) {
|
||||
if (!e) continue;
|
||||
r.render(gl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
327
web/pw-frontend/src/lib/visualizer/webgl/shader.ts
Normal file
|
@ -0,0 +1,327 @@
|
|||
import type { Dictionary } from './util';
|
||||
|
||||
function error(msg: string) {
|
||||
console.error(msg);
|
||||
}
|
||||
|
||||
const defaultShaderType = [
|
||||
"VERTEX_SHADER",
|
||||
"FRAGMENT_SHADER"
|
||||
];
|
||||
|
||||
/// Create Shader from Source string
|
||||
function loadShader(
|
||||
gl: WebGLRenderingContext,
|
||||
shaderSource: string,
|
||||
shaderType: number,
|
||||
opt_errorCallback: any,
|
||||
): WebGLShader {
|
||||
var errFn = opt_errorCallback || error;
|
||||
// Create the shader object
|
||||
var shader = gl.createShader(shaderType);
|
||||
|
||||
// Load the shader source
|
||||
gl.shaderSource(shader, shaderSource);
|
||||
|
||||
// Compile the shader
|
||||
gl.compileShader(shader);
|
||||
|
||||
// Check the compile status
|
||||
var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
|
||||
if (!compiled) {
|
||||
// Something went wrong during compilation; get the error
|
||||
var lastError = gl.getShaderInfoLog(shader);
|
||||
errFn("*** Error compiling shader '" + shader + "':" + lastError);
|
||||
gl.deleteShader(shader);
|
||||
return null;
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
/// Actually Create Program with Shader's
|
||||
function createProgram(
|
||||
gl: WebGLRenderingContext,
|
||||
shaders: WebGLShader[],
|
||||
opt_attribs: string[],
|
||||
opt_locations: number[],
|
||||
opt_errorCallback: any,
|
||||
): WebGLProgram {
|
||||
var errFn = opt_errorCallback || error;
|
||||
var program = gl.createProgram();
|
||||
shaders.forEach(function (shader) {
|
||||
gl.attachShader(program, shader);
|
||||
});
|
||||
if (opt_attribs) {
|
||||
opt_attribs.forEach(function (attrib, ndx) {
|
||||
gl.bindAttribLocation(
|
||||
program,
|
||||
opt_locations ? opt_locations[ndx] : ndx,
|
||||
attrib);
|
||||
});
|
||||
}
|
||||
gl.linkProgram(program);
|
||||
|
||||
// Check the link status
|
||||
var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
|
||||
if (!linked) {
|
||||
// something went wrong with the link
|
||||
var lastError = gl.getProgramInfoLog(program);
|
||||
errFn("Error in program linking:" + lastError);
|
||||
|
||||
gl.deleteProgram(program);
|
||||
return null;
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
export class ShaderFactory {
|
||||
frag_source: string;
|
||||
vert_source: string;
|
||||
|
||||
static async create_factory(frag_url: string, vert_url: string): Promise<ShaderFactory> {
|
||||
const sources = await Promise.all([
|
||||
fetch(frag_url).then((r) => r.text()),
|
||||
fetch(vert_url).then((r) => r.text()),
|
||||
]);
|
||||
|
||||
return new ShaderFactory(sources[0], sources[1]);
|
||||
}
|
||||
|
||||
constructor(frag_source: string, vert_source: string ) {
|
||||
this.frag_source = frag_source;
|
||||
this.vert_source = vert_source;
|
||||
}
|
||||
|
||||
create_shader(
|
||||
gl: WebGLRenderingContext,
|
||||
context?: Dictionary<string>,
|
||||
opt_attribs?: string[],
|
||||
opt_locations?: number[],
|
||||
opt_errorCallback?: any,
|
||||
): Shader {
|
||||
let vert = this.vert_source.slice();
|
||||
let frag = this.frag_source.slice();
|
||||
for (let key in context) {
|
||||
vert = vert.replace(new RegExp("\\$" + key, 'g'), context[key]);
|
||||
frag = frag.replace(new RegExp("\\$" + key, 'g'), context[key]);
|
||||
}
|
||||
|
||||
const shaders = [
|
||||
loadShader(gl, vert, gl.VERTEX_SHADER, opt_errorCallback),
|
||||
loadShader(gl, frag, gl.FRAGMENT_SHADER, opt_errorCallback),
|
||||
];
|
||||
|
||||
return new Shader(createProgram(gl, shaders, opt_attribs, opt_locations, opt_errorCallback));
|
||||
}
|
||||
}
|
||||
|
||||
export class Shader {
|
||||
shader: WebGLProgram;
|
||||
uniformCache: Dictionary<WebGLUniformLocation>;
|
||||
attribCache: Dictionary<number>;
|
||||
|
||||
static async createProgramFromUrls(
|
||||
gl: WebGLRenderingContext,
|
||||
vert_url: string,
|
||||
frag_url: string,
|
||||
context?: Dictionary<string>,
|
||||
opt_attribs?: string[],
|
||||
opt_locations?: number[],
|
||||
opt_errorCallback?: any,
|
||||
): Promise<Shader> {
|
||||
const sources = (await Promise.all([
|
||||
fetch(vert_url).then((r) => r.text()),
|
||||
fetch(frag_url).then((r) => r.text()),
|
||||
])).map(x => {
|
||||
for (let key in context) {
|
||||
x = x.replace(new RegExp("\\$" + key, 'g'), context[key]);
|
||||
}
|
||||
return x;
|
||||
});
|
||||
|
||||
const shaders = [
|
||||
loadShader(gl, sources[0], 35633, opt_errorCallback),
|
||||
loadShader(gl, sources[1], 35632, opt_errorCallback),
|
||||
];
|
||||
return new Shader(createProgram(gl, shaders, opt_attribs, opt_locations, opt_errorCallback));
|
||||
}
|
||||
|
||||
constructor(shader: WebGLProgram) {
|
||||
this.shader = shader;
|
||||
this.uniformCache = {};
|
||||
this.attribCache = {};
|
||||
}
|
||||
|
||||
bind(gl: WebGLRenderingContext) {
|
||||
gl.useProgram(this.shader);
|
||||
}
|
||||
|
||||
// Different locations have different types :/
|
||||
getUniformLocation(gl: WebGLRenderingContext, name: string): WebGLUniformLocation {
|
||||
if (this.uniformCache[name] === undefined) {
|
||||
this.uniformCache[name] = gl.getUniformLocation(this.shader, name);
|
||||
}
|
||||
|
||||
return this.uniformCache[name];
|
||||
}
|
||||
|
||||
getAttribLocation(gl: WebGLRenderingContext, name: string): number {
|
||||
if (this.attribCache[name] === undefined) {
|
||||
this.attribCache[name] = gl.getAttribLocation(this.shader, name);
|
||||
}
|
||||
|
||||
return this.attribCache[name];
|
||||
}
|
||||
|
||||
uniform<T extends Uniform>(
|
||||
gl: WebGLRenderingContext,
|
||||
name: string,
|
||||
uniform: T,
|
||||
) {
|
||||
this.bind(gl);
|
||||
const location = this.getUniformLocation(gl, name);
|
||||
if (location < 0) {
|
||||
console.error("No location found with name " + name);
|
||||
}
|
||||
|
||||
uniform.setUniform(gl, location);
|
||||
}
|
||||
|
||||
clear(gl: WebGLRenderingContext) {
|
||||
gl.deleteProgram(this.shader);
|
||||
}
|
||||
}
|
||||
|
||||
export interface Uniform {
|
||||
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation): void;
|
||||
}
|
||||
|
||||
export class Uniform2fv implements Uniform {
|
||||
data: number[] | Float32Array;
|
||||
constructor(data: number[] | Float32Array) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||
gl.uniform2fv(location, this.data);
|
||||
}
|
||||
}
|
||||
|
||||
export class Uniform3fv implements Uniform {
|
||||
data: number[] | Float32Array;
|
||||
constructor(data: number[] | Float32Array) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||
gl.uniform3fv(location, this.data);
|
||||
}
|
||||
}
|
||||
|
||||
export class Uniform3f implements Uniform {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
|
||||
constructor(x: number, y: number, z: number) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||
gl.uniform3f(location, this.x ,this.y, this.z);
|
||||
}
|
||||
}
|
||||
|
||||
export class Uniform1iv implements Uniform {
|
||||
data: number[] | Int32List;
|
||||
constructor(data: number[] | Int32List) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||
gl.uniform1iv(location, this.data);
|
||||
}
|
||||
}
|
||||
|
||||
export class Uniform1i implements Uniform {
|
||||
texture: number;
|
||||
|
||||
constructor(texture: number) {
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||
gl.uniform1i(location, this.texture);
|
||||
}
|
||||
}
|
||||
|
||||
export class Uniform1f implements Uniform {
|
||||
texture: number;
|
||||
|
||||
constructor(texture: number) {
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||
gl.uniform1f(location, this.texture);
|
||||
}
|
||||
}
|
||||
|
||||
export class Uniform2f implements Uniform {
|
||||
x: number;
|
||||
y: number;
|
||||
|
||||
constructor(xy: number[]) {
|
||||
this.x = xy[0];
|
||||
this.y = xy[1];
|
||||
}
|
||||
|
||||
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||
gl.uniform2f(location, this.x, this.y);
|
||||
}
|
||||
}
|
||||
|
||||
export class Uniform4f implements Uniform {
|
||||
v0: number;
|
||||
v1: number;
|
||||
v2: number;
|
||||
v3: number;
|
||||
|
||||
constructor(xyzw: number[]) {
|
||||
this.v0 = xyzw[0];
|
||||
this.v1 = xyzw[1];
|
||||
this.v2 = xyzw[2];
|
||||
this.v3 = xyzw[3];
|
||||
}
|
||||
|
||||
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||
gl.uniform4f(location, this.v0, this.v1, this.v2, this.v3);
|
||||
}
|
||||
}
|
||||
|
||||
export class UniformMatrix3fv implements Uniform {
|
||||
data: number[] | Float32Array;
|
||||
constructor(data: number[] | Float32Array) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||
gl.uniformMatrix3fv(location, false, this.data);
|
||||
}
|
||||
}
|
||||
|
||||
export class UniformBool implements Uniform {
|
||||
data: boolean;
|
||||
constructor(data: boolean) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||
gl.uniform1i(location, this.data ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
export default Shader;
|
192
web/pw-frontend/src/lib/visualizer/webgl/text.ts
Normal file
|
@ -0,0 +1,192 @@
|
|||
import type { Dictionary } from "./util";
|
||||
import type { Shader, UniformMatrix3fv } from "./shader";
|
||||
import { Texture } from "./texture";
|
||||
import { DefaultRenderable } from "./renderer";
|
||||
import { IndexBuffer, VertexBuffer } from "./buffer";
|
||||
import { VertexBufferLayout, VertexArray } from "./vertexBufferLayout";
|
||||
|
||||
|
||||
export enum Align {
|
||||
Begin,
|
||||
End,
|
||||
Middle,
|
||||
}
|
||||
|
||||
export class GlypInfo {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
}
|
||||
|
||||
export class FontInfo {
|
||||
letterHeight: number;
|
||||
spaceWidth: number;
|
||||
spacing: number;
|
||||
textureWidth: number;
|
||||
textureHeight: number;
|
||||
glyphInfos: Dictionary<GlypInfo>;
|
||||
}
|
||||
|
||||
export class LabelFactory {
|
||||
texture: Texture;
|
||||
font: FontInfo;
|
||||
shader: Shader;
|
||||
|
||||
constructor(gl: WebGLRenderingContext, loc: string, font: FontInfo, shader: Shader) {
|
||||
this.texture = Texture.fromImage(gl, loc, 'font');
|
||||
this.font = font;
|
||||
this.shader = shader;
|
||||
}
|
||||
|
||||
build(gl: WebGLRenderingContext, transform?: UniformMatrix3fv): Label {
|
||||
return new Label(gl, this.shader, this.texture, this.font, transform);
|
||||
}
|
||||
}
|
||||
|
||||
export class Label {
|
||||
inner: DefaultRenderable;
|
||||
|
||||
font: FontInfo;
|
||||
|
||||
constructor(gl: WebGLRenderingContext, shader: Shader, tex: Texture, font: FontInfo, transform?: UniformMatrix3fv) {
|
||||
this.font = font;
|
||||
|
||||
const uniforms = transform ? { "u_trans": transform, "u_trans_next": transform, } : {};
|
||||
const ib = new IndexBuffer(gl, []);
|
||||
const vb_pos = new VertexBuffer(gl, []);
|
||||
const vb_tex = new VertexBuffer(gl, []);
|
||||
|
||||
const layout_pos = new VertexBufferLayout();
|
||||
layout_pos.push(gl.FLOAT, 2, 4, "a_position");
|
||||
|
||||
const layout_tex = new VertexBufferLayout();
|
||||
layout_tex.push(gl.FLOAT, 2, 4, "a_texCoord");
|
||||
|
||||
const vao = new VertexArray();
|
||||
vao.addBuffer(vb_pos, layout_pos);
|
||||
vao.addBuffer(vb_tex, layout_tex);
|
||||
|
||||
this.inner = new DefaultRenderable(ib, vao, shader, [tex], uniforms);
|
||||
}
|
||||
|
||||
getRenderable(): DefaultRenderable {
|
||||
return this.inner;
|
||||
}
|
||||
|
||||
setText(gl: WebGLRenderingContext, text: string, h_align = Align.Begin, v_align = Align.Begin) {
|
||||
const idxs = [];
|
||||
const verts_pos = [];
|
||||
const verts_tex = [];
|
||||
|
||||
const letterHeight = this.font.letterHeight / this.font.textureHeight;
|
||||
let xPos = 0;
|
||||
|
||||
switch (h_align) {
|
||||
case Align.Begin:
|
||||
break;
|
||||
case Align.End:
|
||||
xPos = -1 * [...text].map(n => this.font.glyphInfos[n] ? this.font.glyphInfos[n].width : this.font.spaceWidth).reduce((a, b) => a + b, 0) / this.font.letterHeight;
|
||||
break;
|
||||
case Align.Middle:
|
||||
xPos = -1 * [...text].map(n => this.font.glyphInfos[n] ? this.font.glyphInfos[n].width : this.font.spaceWidth).reduce((a, b) => a + b, 0) / this.font.letterHeight / 2;
|
||||
break;
|
||||
}
|
||||
let yStart = 0;
|
||||
switch (v_align) {
|
||||
case Align.Begin:
|
||||
break;
|
||||
case Align.End:
|
||||
yStart = 1;
|
||||
break;
|
||||
case Align.Middle:
|
||||
yStart = 0.5;
|
||||
break;
|
||||
}
|
||||
|
||||
let j = 0;
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
const info = this.font.glyphInfos[text[i]];
|
||||
if (info) {
|
||||
const dx = info.width / this.font.letterHeight;
|
||||
const letterWidth = info.width / this.font.textureWidth;
|
||||
const x0 = info.x / this.font.textureWidth;
|
||||
const y0 = info.y / this.font.textureHeight;
|
||||
verts_pos.push(xPos, yStart);
|
||||
verts_pos.push(xPos + dx, yStart);
|
||||
verts_pos.push(xPos, yStart-1);
|
||||
verts_pos.push(xPos + dx, yStart-1);
|
||||
|
||||
verts_tex.push(x0, y0);
|
||||
verts_tex.push(x0 + letterWidth, y0);
|
||||
verts_tex.push(x0, y0 + letterHeight);
|
||||
verts_tex.push(x0 + letterWidth, y0 + letterHeight);
|
||||
|
||||
xPos += dx;
|
||||
|
||||
idxs.push(j+0, j+1, j+2, j+1, j+2, j+3);
|
||||
j += 4;
|
||||
} else {
|
||||
// Just move xPos
|
||||
xPos += this.font.spaceWidth / this.font.letterHeight;
|
||||
}
|
||||
}
|
||||
|
||||
this.inner.updateIndexBuffer(gl, idxs);
|
||||
this.inner.updateVAOBuffer(gl, 0, verts_pos);
|
||||
this.inner.updateVAOBuffer(gl, 1, verts_tex);
|
||||
}
|
||||
}
|
||||
|
||||
export function defaultLabelFactory(gl: WebGLRenderingContext, shader: Shader): LabelFactory {
|
||||
const fontInfo = {
|
||||
letterHeight: 8,
|
||||
spaceWidth: 8,
|
||||
spacing: -1,
|
||||
textureWidth: 64,
|
||||
textureHeight: 40,
|
||||
glyphInfos: {
|
||||
'a': { x: 0, y: 0, width: 8, },
|
||||
'b': { x: 8, y: 0, width: 8, },
|
||||
'c': { x: 16, y: 0, width: 8, },
|
||||
'd': { x: 24, y: 0, width: 8, },
|
||||
'e': { x: 32, y: 0, width: 8, },
|
||||
'f': { x: 40, y: 0, width: 8, },
|
||||
'g': { x: 48, y: 0, width: 8, },
|
||||
'h': { x: 56, y: 0, width: 8, },
|
||||
'i': { x: 0, y: 8, width: 8, },
|
||||
'j': { x: 8, y: 8, width: 8, },
|
||||
'k': { x: 16, y: 8, width: 8, },
|
||||
'l': { x: 24, y: 8, width: 8, },
|
||||
'm': { x: 32, y: 8, width: 8, },
|
||||
'n': { x: 40, y: 8, width: 8, },
|
||||
'o': { x: 48, y: 8, width: 8, },
|
||||
'p': { x: 56, y: 8, width: 8, },
|
||||
'q': { x: 0, y: 16, width: 8, },
|
||||
'r': { x: 8, y: 16, width: 8, },
|
||||
's': { x: 16, y: 16, width: 8, },
|
||||
't': { x: 24, y: 16, width: 8, },
|
||||
'u': { x: 32, y: 16, width: 8, },
|
||||
'v': { x: 40, y: 16, width: 8, },
|
||||
'w': { x: 48, y: 16, width: 8, },
|
||||
'x': { x: 56, y: 16, width: 8, },
|
||||
'y': { x: 0, y: 24, width: 8, },
|
||||
'z': { x: 8, y: 24, width: 8, },
|
||||
'0': { x: 16, y: 24, width: 8, },
|
||||
'1': { x: 24, y: 24, width: 8, },
|
||||
'2': { x: 32, y: 24, width: 8, },
|
||||
'3': { x: 40, y: 24, width: 8, },
|
||||
'4': { x: 48, y: 24, width: 8, },
|
||||
'5': { x: 56, y: 24, width: 8, },
|
||||
'6': { x: 0, y: 32, width: 8, },
|
||||
'7': { x: 8, y: 32, width: 8, },
|
||||
'8': { x: 16, y: 32, width: 8, },
|
||||
'9': { x: 24, y: 32, width: 8, },
|
||||
'-': { x: 32, y: 32, width: 8, },
|
||||
'*': { x: 40, y: 32, width: 8, },
|
||||
'!': { x: 48, y: 32, width: 8, },
|
||||
'?': { x: 56, y: 32, width: 8, },
|
||||
},
|
||||
};
|
||||
|
||||
return new LabelFactory(gl, '/static/res/assets/font.png', fontInfo, shader);
|
||||
}
|
106
web/pw-frontend/src/lib/visualizer/webgl/texture.ts
Normal file
|
@ -0,0 +1,106 @@
|
|||
import type { Renderer } from "./renderer";
|
||||
|
||||
export class Texture {
|
||||
texture: WebGLTexture;
|
||||
width: number;
|
||||
height: number;
|
||||
loaded: boolean;
|
||||
name: string;
|
||||
|
||||
static fromImage(
|
||||
gl: WebGLRenderingContext,
|
||||
path: string,
|
||||
name: string,
|
||||
): Texture {
|
||||
const out = new Texture(gl, name);
|
||||
|
||||
const image = new Image();
|
||||
image.onload = out.setImage.bind(out, gl, image);
|
||||
image.onerror = error;
|
||||
image.src = path;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static fromRenderer(
|
||||
gl: WebGLRenderingContext,
|
||||
name: string,
|
||||
width: number,
|
||||
height: number,
|
||||
renderer: Renderer
|
||||
): Texture {
|
||||
const out = new Texture(gl, name);
|
||||
out.width = width;
|
||||
out.height = height;
|
||||
|
||||
gl.texImage2D(
|
||||
gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0,
|
||||
gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
|
||||
const fb = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
|
||||
const attachmentPoint = gl.COLOR_ATTACHMENT0;
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, gl.TEXTURE_2D, out.texture, 0);
|
||||
|
||||
renderer.render(gl, fb, width, height);
|
||||
|
||||
out.loaded = true;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
constructor(
|
||||
gl: WebGLRenderingContext,
|
||||
name: string,
|
||||
) {
|
||||
this.loaded = false;
|
||||
this.name = name;
|
||||
|
||||
this.texture = gl.createTexture();
|
||||
this.bind(gl);
|
||||
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA,
|
||||
gl.UNSIGNED_BYTE, new Uint8Array([255, 0, 0, 255]));
|
||||
}
|
||||
|
||||
setImage(gl: WebGLRenderingContext, image: HTMLImageElement) {
|
||||
this.bind(gl);
|
||||
this.width = image.width;
|
||||
this.height = image.height;
|
||||
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
||||
|
||||
this.unbind(gl);
|
||||
|
||||
this.loaded = true;
|
||||
}
|
||||
|
||||
bind(gl: WebGLRenderingContext, location=0) {
|
||||
gl.activeTexture(gl.TEXTURE0 + location);
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.texture);
|
||||
}
|
||||
|
||||
unbind(gl: WebGLRenderingContext) {
|
||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||
}
|
||||
|
||||
|
||||
getWidth(): number {
|
||||
return this.width;
|
||||
}
|
||||
|
||||
getHeight(): number {
|
||||
return this.height;
|
||||
}
|
||||
}
|
||||
|
||||
function error(e: any) {
|
||||
console.error("IMAGE LOAD ERROR");
|
||||
console.error(e);
|
||||
}
|
229
web/pw-frontend/src/lib/visualizer/webgl/util.ts
Normal file
|
@ -0,0 +1,229 @@
|
|||
import { parse as parsePath } from 'extract-svg-path';
|
||||
import svgMesh3d from 'svg-mesh-3d';
|
||||
|
||||
export interface Dictionary<T> {
|
||||
[Key: string]: T;
|
||||
}
|
||||
|
||||
|
||||
interface OnLoadable {
|
||||
onload: any;
|
||||
}
|
||||
|
||||
export function onload2promise<T extends OnLoadable>(obj: T): Promise<T> {
|
||||
return new Promise(resolve => {
|
||||
obj.onload = () => resolve(obj);
|
||||
});
|
||||
}
|
||||
|
||||
export function resizeCanvasToDisplaySize(
|
||||
canvas: HTMLCanvasElement,
|
||||
multiplier?: number,
|
||||
): boolean {
|
||||
multiplier = multiplier || 1;
|
||||
var width = canvas.clientWidth * multiplier | 0;
|
||||
var height = canvas.clientHeight * multiplier | 0;
|
||||
if (canvas.width !== width || canvas.height !== height) {
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export class FPSCounter {
|
||||
last: number;
|
||||
count: number;
|
||||
_delta: number;
|
||||
_prev: number;
|
||||
|
||||
_frame_start: number;
|
||||
_total_frametime: number;
|
||||
|
||||
constructor() {
|
||||
this.last = 0;
|
||||
this.count = 0;
|
||||
this._delta = 0;
|
||||
this._prev = 0;
|
||||
}
|
||||
|
||||
frame(now: number) {
|
||||
this._frame_start = performance.now();
|
||||
this.count += 1;
|
||||
this._delta = now - this._prev;
|
||||
this._prev = now;
|
||||
|
||||
if (now - this.last > 1000) {
|
||||
this.last = now;
|
||||
console.log(`${this.count} fps, ${(this._total_frametime / this.count).toFixed(2)}ms avg per frame`);
|
||||
this.count = 0;
|
||||
this._total_frametime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
frame_end() {
|
||||
this._total_frametime += (performance.now() - this._frame_start);
|
||||
}
|
||||
|
||||
delta(now: number): number {
|
||||
return this._delta;
|
||||
}
|
||||
}
|
||||
|
||||
export class Resizer {
|
||||
hoovering = false;
|
||||
dragging = false;
|
||||
|
||||
mouse_pos = [0, 0];
|
||||
last_drag = [0, 0];
|
||||
|
||||
viewbox: number[];
|
||||
orig_viewbox: number[];
|
||||
|
||||
el_box: number[];
|
||||
|
||||
scaleX = 1;
|
||||
scaleY = 1;
|
||||
|
||||
constructor(el: HTMLCanvasElement, viewbox: number[], keep_aspect_ratio=false) {
|
||||
viewbox = [-viewbox[0] - viewbox[2], - viewbox[1] - viewbox[3], viewbox[2], viewbox[3]];
|
||||
this.viewbox = [...viewbox];
|
||||
this.el_box = [el.width, el.height];
|
||||
|
||||
if (keep_aspect_ratio) {
|
||||
const or_width = this.viewbox[2];
|
||||
const or_height = this.viewbox[3];
|
||||
|
||||
const width_percentage = this.viewbox[2] / el.width;
|
||||
const height_percentage = this.viewbox[3] / el.height;
|
||||
|
||||
if (width_percentage < height_percentage) {
|
||||
// width should be larger
|
||||
this.viewbox[2] = height_percentage * el.width;
|
||||
} else {
|
||||
// height should be larger
|
||||
this.viewbox[3] = width_percentage * el.height;
|
||||
}
|
||||
|
||||
this.viewbox[0] -= (this.viewbox[2] - or_width) / 2;
|
||||
this.viewbox[1] -= (this.viewbox[3] - or_height) / 2;
|
||||
|
||||
this.scaleX = this.viewbox[2] / this.viewbox[3];
|
||||
}
|
||||
|
||||
this.orig_viewbox = [...this.viewbox];
|
||||
|
||||
el.addEventListener("mouseenter", this.mouseenter.bind(this), { capture: false, passive: true});
|
||||
el.addEventListener("mouseleave", this.mouseleave.bind(this), { capture: false, passive: true});
|
||||
el.addEventListener("mousemove", this.mousemove.bind(this), { capture: false, passive: true});
|
||||
el.addEventListener("mousedown", this.mousedown.bind(this), { capture: false, passive: true});
|
||||
el.addEventListener("mouseup", this.mouseup.bind(this), { capture: false, passive: true});
|
||||
|
||||
window.addEventListener('wheel', this.wheel.bind(this), { capture: false, passive: true});
|
||||
}
|
||||
|
||||
_clip_viewbox() {
|
||||
this.viewbox[0] = Math.max(this.viewbox[0], this.orig_viewbox[0]);
|
||||
this.viewbox[1] = Math.max(this.viewbox[1], this.orig_viewbox[1]);
|
||||
|
||||
this.viewbox[0] = Math.min(this.viewbox[0] + this.viewbox[2], this.orig_viewbox[0] + this.orig_viewbox[2]) - this.viewbox[2];
|
||||
this.viewbox[1] = Math.min(this.viewbox[1] + this.viewbox[3], this.orig_viewbox[1] + this.orig_viewbox[3]) - this.viewbox[3];
|
||||
}
|
||||
|
||||
mouseenter() {
|
||||
this.hoovering = true;
|
||||
}
|
||||
|
||||
mouseleave() {
|
||||
this.hoovering = false;
|
||||
}
|
||||
|
||||
mousemove(e: MouseEvent) {
|
||||
this.mouse_pos = [e.offsetX, this.el_box[1] - e.offsetY];
|
||||
|
||||
if (this.dragging) {
|
||||
const scaleX = this.viewbox[2] / this.el_box[0];
|
||||
const scaleY = this.viewbox[3] / this.el_box[1];
|
||||
|
||||
this.viewbox[0] += (this.last_drag[0] - this.mouse_pos[0]) * scaleX;
|
||||
this.viewbox[1] += (this.last_drag[1] - this.mouse_pos[1]) * scaleY;
|
||||
|
||||
this.last_drag = [...this.mouse_pos];
|
||||
|
||||
this._clip_viewbox();
|
||||
}
|
||||
}
|
||||
|
||||
mousedown() {
|
||||
this.dragging = true;
|
||||
this.last_drag = [...this.mouse_pos];
|
||||
}
|
||||
|
||||
mouseup() {
|
||||
this.dragging = false;
|
||||
}
|
||||
|
||||
wheel(e: WheelEvent) {
|
||||
if (this.hoovering) {
|
||||
const delta = e.deltaY > 0 ? 0.1 * this.viewbox[2] : -0.1 * this.viewbox[2];
|
||||
const dx = delta * this.scaleX;
|
||||
const dy = delta * this.scaleY;
|
||||
|
||||
const mouse_dx = this.mouse_pos[0] / this.el_box[0];
|
||||
const mouse_dy = this.mouse_pos[1] / this.el_box[1];
|
||||
|
||||
this._zoom([dx, dy], [mouse_dx, mouse_dy]);
|
||||
}
|
||||
}
|
||||
|
||||
_zoom(deltas: number[], center: number[]) {
|
||||
this.viewbox[2] += deltas[0];
|
||||
this.viewbox[0] -= deltas[0] * center[0];
|
||||
this.viewbox[2] = Math.min(this.viewbox[2], this.orig_viewbox[2]);
|
||||
|
||||
this.viewbox[3] += deltas[1];
|
||||
this.viewbox[1] -= deltas[1] * center[1];
|
||||
this.viewbox[3] = Math.min(this.viewbox[3], this.orig_viewbox[3]);
|
||||
|
||||
this._clip_viewbox();
|
||||
}
|
||||
|
||||
get_viewbox(): number[] {
|
||||
return this.viewbox;
|
||||
}
|
||||
|
||||
get_mouse_pos(): number[] {
|
||||
return this.mouse_pos;
|
||||
}
|
||||
}
|
||||
|
||||
export class Mesh {
|
||||
cells: number[];
|
||||
positions: number[];
|
||||
|
||||
constructor(mesh: any) {
|
||||
this.cells = mesh.cells.flat();
|
||||
this.positions = mesh.positions.flat();
|
||||
}
|
||||
}
|
||||
|
||||
export async function url_to_mesh(url: string): Promise<Mesh> {
|
||||
|
||||
return new Promise(function(resolve) {
|
||||
fetch(url)
|
||||
.then(resp => resp.text())
|
||||
.then(data => {
|
||||
// var div = document.createElement('div');
|
||||
// div.innerHTML = data;
|
||||
// var svg = div.querySelector('svg');
|
||||
|
||||
var svgPath = parsePath(data);
|
||||
var mesh = svgMesh3d(svgPath, {
|
||||
delaunay: false,
|
||||
scale: 10,
|
||||
});
|
||||
|
||||
resolve(new Mesh(mesh));
|
||||
})
|
||||
});
|
||||
}
|
115
web/pw-frontend/src/lib/visualizer/webgl/vertexBufferLayout.ts
Normal file
|
@ -0,0 +1,115 @@
|
|||
import type { VertexBuffer } from './buffer';
|
||||
import type { Shader } from './shader';
|
||||
|
||||
export class VertexBufferElement {
|
||||
type: number;
|
||||
amount: number;
|
||||
type_size: number;
|
||||
normalized: boolean;
|
||||
index: string;
|
||||
|
||||
constructor(
|
||||
type: number,
|
||||
amount: number,
|
||||
type_size: number,
|
||||
index: string,
|
||||
normalized: boolean,
|
||||
) {
|
||||
this.type = type;
|
||||
this.amount = amount;
|
||||
this.type_size = type_size;
|
||||
this.normalized = normalized;
|
||||
this.index = index;
|
||||
}
|
||||
}
|
||||
|
||||
export class VertexBufferLayout {
|
||||
elements: VertexBufferElement[];
|
||||
stride: number;
|
||||
offset: number;
|
||||
|
||||
constructor(offset = 0) {
|
||||
this.elements = [];
|
||||
this.stride = 0;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
// Maybe wrong normalized type
|
||||
push(
|
||||
type: number,
|
||||
amount: number,
|
||||
type_size: number,
|
||||
index: string,
|
||||
normalized = false,
|
||||
) {
|
||||
this.elements.push(new VertexBufferElement(type, amount, type_size, index, normalized));
|
||||
this.stride += amount * type_size;
|
||||
}
|
||||
|
||||
getElements(): VertexBufferElement[] {
|
||||
return this.elements;
|
||||
}
|
||||
|
||||
getStride(): number {
|
||||
return this.stride;
|
||||
}
|
||||
}
|
||||
|
||||
// glEnableVertexAttribArray is to specify what location of the current program the follow data is needed
|
||||
// glVertexAttribPointer tells gl that that data is at which location in the supplied data
|
||||
export class VertexArray {
|
||||
// There is no renderer ID, always at bind buffers and use glVertexAttribPointer
|
||||
buffers: VertexBuffer[];
|
||||
layouts: VertexBufferLayout[];
|
||||
|
||||
constructor() {
|
||||
this.buffers = [];
|
||||
this.layouts = [];
|
||||
}
|
||||
|
||||
addBuffer(vb: VertexBuffer, layout: VertexBufferLayout) {
|
||||
this.buffers.push(vb);
|
||||
this.layouts.push(layout);
|
||||
}
|
||||
|
||||
updateBuffer(gl: WebGLRenderingContext, index: number, data: number[]) {
|
||||
this.buffers[index].updateData(gl, data);
|
||||
}
|
||||
|
||||
/// Bind buffers providing program data
|
||||
bind(gl: WebGLRenderingContext, shader: Shader) {
|
||||
shader.bind(gl);
|
||||
for(let i = 0; i < this.buffers.length; i ++) {
|
||||
const buffer = this.buffers[i];
|
||||
const layout = this.layouts[i];
|
||||
|
||||
buffer.bind(gl);
|
||||
const elements = layout.getElements();
|
||||
let offset = layout.offset;
|
||||
|
||||
for (let j = 0; j < elements.length; j ++) {
|
||||
const element = elements[j];
|
||||
const location = shader.getAttribLocation(gl, element.index);
|
||||
|
||||
if (location >= 0) {
|
||||
gl.enableVertexAttribArray(location);
|
||||
gl.vertexAttribPointer(
|
||||
location, element.amount, element.type,
|
||||
element.normalized, layout.stride, offset
|
||||
);
|
||||
}
|
||||
|
||||
offset += element.amount * element.type_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Undo bind operation
|
||||
unbind(gl: WebGLRenderingContext) {
|
||||
this.layouts.forEach((layout) => {
|
||||
layout.getElements().forEach((_, index) => {
|
||||
gl.disableVertexAttribArray(index);
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
9
web/pw-frontend/src/main.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import App from './App.svelte'
|
||||
import load_wasm_module from "planetwars-rs";
|
||||
|
||||
load_wasm_module().then(() => {
|
||||
const app = new App({
|
||||
target: document.getElementById('app')
|
||||
})
|
||||
});
|
||||
|
2
web/pw-frontend/src/vite-env.d.ts
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/// <reference types="svelte" />
|
||||
/// <reference types="vite/client" />
|
7
web/pw-frontend/svelte.config.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import sveltePreprocess from 'svelte-preprocess'
|
||||
|
||||
export default {
|
||||
// Consult https://github.com/sveltejs/svelte-preprocess
|
||||
// for more information about preprocessors
|
||||
preprocess: sveltePreprocess()
|
||||
}
|
20
web/pw-frontend/tsconfig.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "esnext",
|
||||
|
||||
"resolveJsonModule": true,
|
||||
"baseUrl": ".",
|
||||
/**
|
||||
* Typecheck JS in `.svelte` and `.js` files by default.
|
||||
* Disable checkJs if you'd like to use dynamic types in JS.
|
||||
* Note that setting allowJs false does not prevent the use
|
||||
* of JS in `.svelte` files.
|
||||
*/
|
||||
"allowJs": false,
|
||||
"checkJs": false
|
||||
},
|
||||
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"]
|
||||
}
|
12
web/pw-frontend/vite.config.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { defineConfig } from 'vite'
|
||||
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
||||
import nodePolyfills from 'rollup-plugin-polyfill-node'
|
||||
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
svelte(),
|
||||
nodePolyfills()
|
||||
],
|
||||
})
|