summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2022-06-22 17:41:59 -0400
committerJon Santmyer <jon@jonsantmyer.com>2022-06-22 17:41:59 -0400
commit5e3a2492c7bb73daa4e27398daaf490d09980ff3 (patch)
tree75178d823d596b6a898002c3f1d45b9ceede0e1e
downloadsystemviewer-5e3a2492c7bb73daa4e27398daaf490d09980ff3.tar.gz
systemviewer-5e3a2492c7bb73daa4e27398daaf490d09980ff3.tar.bz2
systemviewer-5e3a2492c7bb73daa4e27398daaf490d09980ff3.zip
Base system viewer with data loaded from csv files
-rw-r--r--.gitignore8
-rw-r--r--Makefile25
-rw-r--r--data/final.csv211
-rw-r--r--data/sol_asteroids.csv1915
-rw-r--r--data/sol_planets.csv9
-rw-r--r--data/sol_satellites.csv211
-rw-r--r--include/camera.hpp96
-rw-r--r--include/csv.hpp115
-rw-r--r--include/ecs.hpp139
-rw-r--r--include/entitycomponents.hpp58
-rw-r--r--include/game.hpp52
-rw-r--r--include/input.hpp71
-rw-r--r--include/keybind.hpp71
-rw-r--r--include/shape.hpp197
-rw-r--r--include/straw.hpp312
-rw-r--r--include/system.hpp82
-rw-r--r--include/timeman.hpp27
-rw-r--r--include/units.hpp166
-rw-r--r--include/util.hpp45
-rw-r--r--include/vex.hpp104
-rw-r--r--include/window.hpp69
-rw-r--r--src/camera.cpp197
-rw-r--r--src/game.cpp115
-rw-r--r--src/input.cpp37
-rw-r--r--src/keybind.cpp64
-rw-r--r--src/main.cpp26
-rw-r--r--src/system.cpp517
-rw-r--r--src/timeman.cpp49
-rw-r--r--src/units.cpp61
-rw-r--r--src/window.cpp72
30 files changed, 5121 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9425e48
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+keybinds.csv
+compile_commands.json
+bin
+.cache
+spacelike
+*.o
+
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..8176c1f
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,25 @@
+PWD := $(shell pwd)
+
+SDIR := $(PWD)/src
+IDIR := $(PWD)/include
+ODIR := $(PWD)/bin
+
+SFILES := $(wildcard $(SDIR)/*.cpp)
+OFILES := $(patsubst $(SDIR)/%.cpp,$(ODIR)/%.o,$(SFILES))
+
+OUT := spacelike
+
+CC := g++
+CFLAGS := -std=c++20 -Wall -Wextra -MP -MD -I$(IDIR) -g -Wno-unused
+
+-include $(SDIR/:.cpp=.d)
+
+all: ${OFILES}
+ $(CC) $(CFLAGS) ${OFILES} -o $(OUT)
+
+clean:
+ rm ${OFILES}
+
+$(ODIR)/%.o : $(SDIR)/%.cpp
+ $(CC) $(CFLAGS) -c $< -o $@
+
diff --git a/data/final.csv b/data/final.csv
new file mode 100644
index 0000000..ffa2e5f
--- /dev/null
+++ b/data/final.csv
@@ -0,0 +1,211 @@
+,,0,0,0,0,0,0
+Hydra,Pluto,0.000432493,0.006,8.02782e-09,0.00290378,330.6,143.4
+Charon,Pluto,0.000131018,0,0.00026562,0.0951185,192.4,0
+Neso,Neptune,0.334536,0.447,0,0,123.2,338.3
+Sao,Neptune,0.14961,0.299,0,0,179.6,90.9
+Hippocamp,Neptune,0.000703887,0.001,0,0,286.5,346.4
+Proteus,Neptune,0.000786107,0,6.48101e-06,0.0326479,276.8,0
+Galatea,Neptune,0.000414444,0,4.76401e-07,0.0123999,86.7,0
+Despina,Neptune,0.000350941,0,2.9284e-07,0.0116151,125.1,0
+Ferdinand,Uranus,0.138023,0.397,0,0,256.7,79.1
+Trinculo,Uranus,0.0568524,0.219,0,0,88.5,130.1
+Caliban,Uranus,0.0483296,0.204,0,0,224.9,8.3
+Cupid,Uranus,0.000497333,0.005,0,0,160.6,13.5
+Mab,Uranus,0.000653084,0.003,0,0,348,237.9
+Perdita,Uranus,0.000510702,0.002,0,0,32.2,310.4
+Belinda,Uranus,0.000503349,0,0,0,121.3,0
+Rosalind,Uranus,0.000467253,0,0,0,79.4,0
+Juliet,Uranus,0.000430487,0.001,0,0,124.8,291.5
+Cressida,Uranus,0.000413107,0,0,0,332.8,0
+Bianca,Uranus,0.000395728,0.001,0,0,236.2,97
+Cordelia,Uranus,0.000332892,0,0,0,95,0
+Puck,Uranus,0.000574874,0,0,0,174.5,0
+Miranda,Uranus,0.000868328,0.001,1.07874e-05,0.0370115,72.4,155.6
+Ophelia,Uranus,0.000359631,0.011,0,0,280.5,344.3
+Titania,Uranus,0.00291649,0.001,0.000569223,0.123827,53.2,202
+Ariel,Uranus,0.00127609,0.001,0.000209476,0.0908649,119.8,83.3
+S2019_s01,Saturn,0.0751749,0.463,0,0,36.6,86.6
+Portia,Uranus,0.000441851,0,0,0,343.7,0
+S2007_s02,Saturn,0.111753,0.179,0,0,84.1,57.7
+S2006_s03,Saturn,0.149922,0.379,0,0,167.1,188.7
+S2004_s39,Saturn,0.155089,0.102,0,0,98,199.8
+S2004_s38,Saturn,0.148839,0.541,0,0,101.4,346.6
+S2004_s36,Saturn,0.15668,0.617,0,0,138.8,204.4
+S2004_s33,Saturn,0.157629,0.514,0,0,128.3,309.7
+S2004_s29,Saturn,0.114106,0.488,0,0,183.8,318.9
+S2004_s28,Saturn,0.146011,0.161,0,0,95.9,186.6
+S2004_s26,Saturn,0.174515,0.147,0,0,153.2,151.7
+S2004_s24,Saturn,0.156058,0.072,0,0,289.6,181
+S2004_s22,Saturn,0.137689,0.216,0,0,102.8,118.9
+S2007_s03,Saturn,0.126593,0.185,0,0,292.7,111.9
+S2004_s21,Saturn,0.154621,0.409,0,0,187.5,182
+S2004_s27,Saturn,0.132689,0.157,0,0,268.1,142.7
+S2004_s20,Saturn,0.128738,0.182,0,0,122.5,290.1
+S2004_s17,Saturn,0.130002,0.18,0,0,228.5,180.8
+S2004_s13,Saturn,0.123037,0.259,0,0,41.1,346.2
+S2004_s07,Saturn,0.140376,0.529,0,0,79.8,84
+Tarqeq,Saturn,0.120069,0.168,0,0,161,34.8
+Greip,Saturn,0.123377,0.315,0,0,314.5,152.2
+Jarnsaxa,Saturn,0.129373,0.218,0,0,198.7,237.4
+Surtur,Saturn,0.153351,0.446,0,0,136.2,303.7
+Skoll,Saturn,0.118097,0.464,0,0,45,193.1
+Psamathe,Neptune,0.312181,0.451,0,0,70.2,261.3
+Kari,Saturn,0.147683,0.476,0,0,286,163.9
+Margaret,Uranus,0.0940521,0.678,0,0,119.9,90.4
+Hyrrokkin,Saturn,0.123264,0.336,0,0,291.8,273.1
+S2004_s37,Saturn,0.106586,0.446,0,0,185.9,77.2
+Eirene,Jupiter,0.154119,0.258,0,0,329.7,94.8
+S2006_s01,Saturn,0.125537,0.141,0,0,96.6,155
+S2017_j3,Jupiter,0.139982,0.231,0,0,193.3,92.9
+Nereid,Neptune,0.036792,0.749,0,0.0266834,318,290.3
+Chaldene,Jupiter,0.153281,0.265,0,0,266.2,335
+S2011_j2,Jupiter,0.153139,0.355,0,0,284,218.7
+S2010_j1,Jupiter,0.155014,0.252,0,0,161.1,344.2
+Stephano,Uranus,0.0535034,0.218,0,0,190.2,352.6
+Eukelade,Jupiter,0.154196,0.277,0,0,203.6,283.7
+Aoede,Jupiter,0.158947,0.436,0,0,198.8,72.9
+Hegemone,Jupiter,0.156076,0.358,0,0,233.7,282.2
+S2003_j23,Jupiter,0.159289,0.313,0,0,168.5,163.2
+Enceladus,Saturn,0.00159361,0.005,1.80886e-05,0.0395699,57,119.5
+S2004_s35,Saturn,0.146827,0.237,0,0,320.2,154.2
+Kale,Jupiter,0.154097,0.262,0,0,212.7,283.6
+Pallene,Saturn,0.00141914,0.004,0,0,2,194.9
+Sponde,Jupiter,0.157377,0.322,0,0,173.8,184.9
+Calypso,Saturn,0.00197195,0.001,0,0,-0,221.6
+Euporie,Jupiter,0.128784,0.148,0,0,72.2,329.8
+Phobos,Mars,6.28351e-05,0.015,1.77791e-09,0.00173913,189.6,216.3
+Carme,Jupiter,0.154711,0.256,0,0,234,155
+Euanthe,Jupiter,0.13922,0.239,0,0,336.5,169.8
+Francisco,Uranus,0.0286301,0.139,0,0,129.5,297.3
+S2016_j2,Jupiter,0.124963,0.217,0,0,57.6,344.2
+Laomedeia,Neptune,0.157809,0.418,0,0,248.3,146
+S2017_j6,Jupiter,0.155385,0.336,0,0,150.2,100
+Thelxinoe,Jupiter,0.140216,0.228,0,0,267.9,333.4
+Aitne,Jupiter,0.154176,0.277,0,0,106,81.3
+Hermippe,Jupiter,0.141102,0.219,0,0,134.7,356.6
+Pasithee,Jupiter,0.152721,0.27,0,0,216,295.2
+Larissa,Neptune,0.000491317,0.001,6.39315e-07,0.0150683,165.5,247.3
+Sycorax,Uranus,0.0814183,0.521,0,0,146.2,211.4
+Deimos,Mars,0.000157088,0,2.41336e-10,0.00097316,205,0
+Fornjot,Saturn,0.168091,0.208,0,0,214.5,324.8
+Naiad,Neptune,0.000322197,0,2.13992e-08,0.00455188,89.7,0
+Janus,Saturn,0.00101271,0.007,3.17651e-07,0.0140009,111.7,11.1
+S2003_j18,Jupiter,0.13594,0.09,0,0,66.1,304.4
+Magaclite,Jupiter,0.158054,0.421,0,0,138.1,85.1
+Triton,Neptune,0.00237169,0,0.00358366,0.212306,63,0
+Himalia,Jupiter,0.0764757,0.16,3.80192e-07,0.0133417,66.5,328.4
+Halimede,Neptune,0.105307,0.566,0,0,173.9,113.5
+Orthosie,Jupiter,0.139715,0.299,0,0,200.7,140.1
+Leda,Jupiter,0.0745091,0.162,0,0,233.4,270.9
+Adrastea,Jupiter,0.000862312,0,3.51217e-10,0.00128708,214.5,0
+Helike,Jupiter,0.139813,0.153,0,0,44.2,118.1
+Loge,Saturn,0.15414,0.186,0,0,337.2,32.8
+Skathi,Saturn,0.104514,0.272,0,0,114.7,203.5
+Bebhionn,Saturn,0.114413,0.468,0,0,168,358.1
+Bergelmir,Saturn,0.129253,0.142,0,0,306.5,133.4
+Io,Jupiter,0.00281956,0.004,0.0149516,0.285903,330.9,49.1
+Amalthea,Jupiter,0.00121258,0.003,4.12831e-07,0.0131063,310.6,180.1
+Nix,Pluto,0.000325539,0,7.52608e-09,0.0028253,84.8,0
+Callisto,Jupiter,0.0125851,0.007,0.0180106,0.378324,87.4,43.8
+Helene,Saturn,0.0025241,0.007,1.20417e-09,0.0028253,-64.5,194.3
+Prometheus,Saturn,0.000931831,0.002,2.68681e-08,0.00676503,135.4,341.9
+Desdemona,Uranus,0.000419124,0,0,0,160.4,0
+Thyone,Jupiter,0.140229,0.233,0,0,244.4,343.5
+S2016_j1,Jupiter,0.139057,0.232,0,0,192.4,197.8
+Iapetus,Saturn,0.0238085,0.028,0.000302335,0.115257,74.8,254.5
+Europa,Jupiter,0.00448603,0.009,0.00803462,0.244985,345.4,45
+S2003_j4,Jupiter,0.153254,0.328,0,0,242.8,194.4
+Fenrir,Saturn,0.150096,0.135,0,0,131.7,121
+Eurydome,Jupiter,0.15307,0.294,0,0,286.3,340.2
+Metis,Jupiter,0.000855627,0,6.27173e-09,0.00337467,166,0
+Isonoe,Jupiter,0.153621,0.249,0,0,124.9,213.5
+Sinope,Jupiter,0.158317,0.264,0,0,167.5,96.6
+Ganymede,Jupiter,0.00715518,0.001,0.0248055,0.412996,324.8,198.3
+Lysithea,Jupiter,0.078215,0.117,0,0,331.5,47.4
+Mimas,Saturn,0.00124333,0.02,6.28049e-06,0.0311097,275.3,160.4
+Praxidike,Jupiter,0.139945,0.246,0,0,112.2,357.2
+S2004_s31,Saturn,0.116974,0.202,0,0,255.4,262.7
+S2017_j9,Jupiter,0.145515,0.2,0,0,261.5,130.7
+Aegaeon,Saturn,0.00111967,0,0,0,4.4,0
+Kallichore,Jupiter,0.153891,0.252,0,0,54.2,310.1
+Siarnaq,Saturn,0.121539,0.28,0,0,201.3,65.9
+Setebos,Uranus,0.116606,0.588,0,0,281.3,214.4
+Autonoe,Jupiter,0.159043,0.33,0,0,145.7,228.3
+Ananke,Jupiter,0.140607,0.237,0,0,259.4,56.2
+Taygete,Jupiter,0.154467,0.253,0,0,95.7,341
+Callirrhoe,Jupiter,0.159063,0.297,0,0,107.1,180.5
+Kore,Jupiter,0.161802,0.328,0,0,31.8,229.3
+Themisto,Jupiter,0.0494559,0.34,0,0,284.7,236.2
+Pasiphae,Jupiter,0.156875,0.412,0,0,277.8,264.8
+Albiorix,Saturn,0.10958,0.48,0,0,32.8,55.9
+Erinome,Jupiter,0.153965,0.276,0,0,265.5,98.2
+Kalyke,Jupiter,0.155768,0.26,0,0,256,130.3
+Mneme,Jupiter,0.13918,0.247,0,0,253.7,18.5
+S2017_j1,Jupiter,0.158724,0.328,0,0,286.5,252.2
+S2017_j8,Jupiter,0.152739,0.255,0,0,350.4,146.9
+S2003_j9,Jupiter,0.155078,0.263,0,0,354.6,199.6
+Titan,Saturn,0.0081679,0.029,0.0225234,0.404137,11.7,78.3
+Eupheme,Jupiter,0.13883,0.241,0,0,359.1,316.6
+Thalassa,Neptune,0.000334898,0,5.91801e-08,0.00627845,165.7,0
+Philophrosyne,Jupiter,0.151102,0.229,0,0,69.5,271.6
+Farbauti,Saturn,0.136299,0.241,0,0,282.8,343
+Methone,Saturn,0.00130149,0.002,0,0,0,315.5
+S2003_j19,Jupiter,0.154791,0.265,0,0,218.4,123.4
+S2017_j2,Jupiter,0.153433,0.272,0,0,293.3,137.5
+Bestla,Saturn,0.134661,0.52,0,0,238.5,81.1
+Pandia,Jupiter,0.0767457,0.179,0,0,153.9,194.3
+S2004_s34,Saturn,0.161433,0.282,0,0,34.7,346.5
+S2004_s25,Saturn,0.140049,0.519,0,0,208,268.2
+S2010_j2,Jupiter,0.138993,0.248,0,0,306.3,15.1
+S2017_j5,Jupiter,0.155124,0.257,0,0,66.9,211.7
+S2017_j7,Jupiter,0.140141,0.233,0,0,359.1,119.4
+Carpo,Jupiter,0.113921,0.416,0,0,339.8,86.6
+Ersa,Jupiter,0.076211,0.116,0,0,263.4,304.7
+Mundilfari,Saturn,0.124688,0.21,0,0,92.8,309.7
+Elara,Jupiter,0.0782919,0.211,0,0,330.7,140.1
+S2011_j1,Jupiter,0.154578,0.271,0,0,248.4,251.8
+Arche,Jupiter,0.154399,0.261,0,0,39.8,213.5
+S2003_j10,Jupiter,0.157598,0.264,0,0,286.9,227.5
+S2003_j2,Jupiter,0.140361,0.225,0,0,35.2,200.4
+S2004_s32,Saturn,0.141392,0.254,0,0,169.4,32.7
+S2003_j12,Jupiter,0.14013,0.235,0,0,201.3,277.9
+S2003_j16,Jupiter,0.139592,0.243,0,0,307.4,24.6
+Polydeuces,Saturn,0.0025241,0.019,0,0,359,94.1
+Herse,Jupiter,0.154752,0.262,0,0,141.2,101.2
+Cyllene,Jupiter,0.158122,0.419,0,0,121.3,47.8
+S2003_j24,Jupiter,0.152993,0.259,0,0,131.8,24.2
+Tethys,Saturn,0.00197195,0.001,0.000103392,0.0833621,0,335.3
+Harpalyke,Jupiter,0.139655,0.232,0,0,219.3,71.3
+Narvi,Saturn,0.12934,0.43,0,0,114.2,170
+Dione,Saturn,0.00252477,0.002,0.000183426,0.088118,212,116
+Rhea,Saturn,0.00352411,0.001,0.000386193,0.11984,31.5,44.3
+Umbriel,Uranus,0.0017781,0.004,0.00021349,0.0917752,258.3,157.5
+Thebe,Jupiter,0.00148331,0.018,7.56371e-08,0.00773819,182.1,26.6
+Pandora,Saturn,0.000947206,0.004,2.32305e-08,0.00637263,123.9,217.9
+S2004_s23,Saturn,0.143431,0.437,0,0,65.1,22.8
+Aegir,Saturn,0.138712,0.252,0,0,26,242.7
+Hyperion,Saturn,0.00990322,0.105,9.29446e-07,0.0211898,122.9,214
+Prospero,Uranus,0.108738,0.439,0,0,125.3,251.9
+S2004_s30,Saturn,0.138444,0.087,0,0,336.5,269.3
+Phoebe,Saturn,0.0864277,0.164,1.3918e-06,0.0167164,308,240.3
+Telesto,Saturn,0.00197195,0.001,0,0,360,66.2
+S2004_s12,Saturn,0.13293,0.327,0,0,1.6,87.1
+Epimetheus,Saturn,0.00101205,0.02,8.81555e-08,0.00913514,197.2,96.3
+Oberon,Uranus,0.00389979,0.001,0.000515035,0.11951,139.7,182.4
+Atlas,Saturn,0.000920468,0.001,9.28217e-10,0.00237011,289.1,82.3
+Pan,Saturn,0.000893061,0,7.02434e-10,0.00219746,146.6,0
+Daphnis,Saturn,0.000912446,0,0,0,153.6,0
+Anthe,Saturn,0.00132422,0.002,0,0,351.4,293.4
+Dia,Jupiter,0.081955,0.232,0,0,309.6,176.8
+Ymir,Saturn,0.154601,0.334,0,0,228.7,21.4
+Kerberos,Pluto,0.000386369,0,2.75956e-09,0.000941767,303.5,0
+Kiviuq,Saturn,0.0758233,0.212,0,0,171,90.6
+Ijiraq,Saturn,0.0762578,0.272,0,0,17.3,92.9
+Paaliaq,Saturn,0.101378,0.341,0,0,321.3,238.7
+Tarvos,Saturn,0.121947,0.538,0,0,265.8,274.1
+Iocaste,Jupiter,0.140822,0.227,0,0,215.5,244.7
+Suttungr,Saturn,0.130136,0.114,0,0,321.1,34.3
+Erriapus,Saturn,0.117662,0.472,0,0,294.8,282.5
+Thrymr,Saturn,0.136486,0.466,0,0,30.1,125.4
+Styx,Pluto,0.000283426,0,0,0.000816198,180.9,0
+Hati,Saturn,0.132809,0.371,0,0,163.6,21.3
diff --git a/data/sol_asteroids.csv b/data/sol_asteroids.csv
new file mode 100644
index 0000000..ac5b2d3
--- /dev/null
+++ b/data/sol_asteroids.csv
@@ -0,0 +1,1915 @@
+Ceres,2.766,0.0785,939.4,291.38,73.64,1
+Pallas,2.771,0.2300,513,272.48,310.70,2
+Juno,2.669,0.2569,246.596,261.30,247.94,3
+Vesta,2.361,0.0882,525.4,7.03,151.09,4
+Astraea,2.575,0.1901,106.699,160.98,358.74,5
+Hebe,2.426,0.2031,185.18,347.50,239.51,6
+Iris,2.387,0.2295,199.83,47.64,145.34,7
+Flora,2.202,0.1561,147.491,136.26,285.55,8
+Metis,2.385,0.1236,190,184.56,6.16,9
+Hygiea,3.142,0.1116,407.12,328.90,312.49,10
+Parthenope,2.453,0.0995,142.887,175.42,195.60,11
+Victoria,2.334,0.2207,115.087,49.75,69.67,12
+Egeria,2.577,0.0854,202.636,66.24,80.15,13
+Irene,2.586,0.1659,152,42.04,97.71,14
+Eunomia,2.644,0.1866,231.689,152.50,98.63,15
+Psyche,2.924,0.1339,226,125.13,229.22,16
+Thetis,2.471,0.1329,84.899,197.57,135.81,17
+Melpomene,2.296,0.2179,139.594,190.37,228.12,18
+Fortuna,2.443,0.1570,200,95.09,182.47,19
+Massalia,2.409,0.1431,135.680,20.51,257.56,20
+Lutetia,2.435,0.1635,95.76,243.38,250.16,21
+Kalliope,2.91,0.0984,167.536,33.48,357.60,22
+Thalia,2.63,0.2327,107.53,207.14,60.99,23
+Themis,3.142,0.1224,198,171.96,107.60,24
+Phocaea,2.399,0.2550,61.054,78.04,90.25,25
+Proserpina,2.655,0.0894,94.80,333.30,193.66,26
+Euterpe,2.348,0.1721,96,249.69,356.26,27
+Bellona,2.775,0.1515,120.90,126.85,343.83,28
+Amphitrite,2.554,0.0734,189.559,165.88,63.09,29
+Urania,2.366,0.1277,92.787,300.48,87.00,30
+Euphrosyne,3.164,0.2179,267.080,262.86,61.56,31
+Pomona,2.587,0.0817,80.76,269.62,338.68,32
+Polyhymnia,2.875,0.3317,52.929,184.13,338.49,33
+Circe,2.687,0.1066,132.992,351.03,330.22,34
+Leukothea,2.993,0.2248,103.055,45.45,213.46,35
+Atalante,2.747,0.3056,132.842,156.20,47.78,36
+Fides,2.641,0.1759,108.35,211.33,62.62,37
+Leda,2.742,0.1531,92.255,222.44,169.20,38
+Laetitia,2.77,0.1117,179.484,155.00,209.54,39
+Harmonia,2.267,0.0465,111.251,37.30,268.65,40
+Daphne,2.761,0.2746,205.495,349.11,45.92,41
+Isis,2.442,0.2227,110.997,101.85,237.18,42
+Ariadne,2.203,0.1688,71.340,79.28,16.31,43
+Nysa,2.423,0.1489,70.64,342.99,344.19,44
+Eugenia,2.721,0.0836,202.327,258.63,87.66,45
+Hestia,2.525,0.1728,131.471,315.63,177.35,46
+Aglaja,2.882,0.1301,168.174,253.30,315.06,47
+Doris,3.115,0.0706,216.473,250.21,251.98,48
+Pales,3.098,0.2215,166.252,60.40,113.11,49
+Virginia,2.65,0.2852,84.074,27.20,199.90,50
+Nemausa,2.366,0.0676,138.159,7.67,1.91,51
+Europa,3.095,0.1108,303.918,58.66,343.14,52
+Kalypso,2.619,0.2025,97.262,295.87,314.09,53
+Alexandra,2.712,0.1970,160.120,238.89,345.18,54
+Pandora,2.759,0.1438,84.794,215.91,5.42,55
+Melete,2.596,0.2380,121.333,122.30,104.93,56
+Mnemosyne,3.157,0.1099,112.59,319.48,210.36,57
+Concordia,2.702,0.0436,106.517,157.83,33.45,58
+Elpis,2.713,0.1173,165.119,20.11,210.67,59
+Echo,2.392,0.1850,43.218,114.90,271.10,60
+Danae,2.984,0.1648,85.937,103.20,12.66,61
+Erato,3.13,0.1679,106.921,56.90,277.36,62
+Ausonia,2.396,0.1274,116.044,45.15,296.22,63
+Angelina,2.681,0.1256,58.292,260.96,180.67,64
+Cybele,3.433,0.1141,237.26,55.63,103.43,65
+Maja,2.645,0.1733,71.82,248.43,43.75,66
+Asia,2.422,0.1848,56.309,180.09,107.02,67
+Leto,2.783,0.1850,122.509,113.81,304.61,68
+Hesperia,2.975,0.1702,138.13,133.30,288.91,69
+Panopaea,2.615,0.1806,127.911,303.07,255.66,70
+Niobe,2.757,0.1749,83.42,119.07,267.19,71
+Feronia,2.266,0.1205,74.966,295.40,103.13,72
+Klytia,2.664,0.0418,44.590,20.26,55.41,73
+Galatea,2.782,0.2361,118.71,127.08,174.66,74
+Eurydike,2.675,0.3036,62.377,187.07,339.44,75
+Freia,3.414,0.1663,145.423,80.60,252.14,76
+Frigga,2.668,0.1330,61.390,149.59,61.67,77
+Diana,2.622,0.2058,120.60,190.69,152.85,78
+Eurynome,2.445,0.1903,63.479,126.14,201.54,79
+Sappho,2.296,0.2002,68.563,20.84,139.49,80
+Terpsichore,2.852,0.2114,117.727,191.82,51.53,81
+Alkmene,2.764,0.2205,57.621,30.43,111.05,82
+Beatrix,2.434,0.0812,110.503,128.78,169.32,83
+Klio,2.362,0.2364,79.16,18.91,15.04,84
+Io,2.652,0.1942,154.79,89.11,122.82,85
+Semele,3.106,0.2158,109.929,171.86,308.87,86
+Sylvia,3.48,0.0940,253.051,244.12,263.93,87
+Thisbe,2.769,0.1618,232,262.59,36.53,88
+Julia,2.55,0.1847,145.483,19.81,45.04,89
+Antiope,3.147,0.1668,115.974,321.32,245.17,90
+Aegina,2.59,0.1069,103.402,43.15,74.39,91
+Undina,3.191,0.1060,126.42,353.89,238.23,92
+Minerva,2.755,0.1389,154.155,332.17,275.17,93
+Aurora,3.158,0.0947,204.89,124.73,60.22,94
+Arethusa,3.063,0.1532,147.969,258.17,153.66,95
+Aegle,3.049,0.1414,177.774,289.86,208.23,96
+Klotho,2.668,0.2577,100.717,177.22,268.57,97
+Ianthe,2.688,0.1875,132.788,349.69,158.49,98
+Dike,2.665,0.1961,67.354,110.80,195.74,99
+Hekate,3.087,0.1691,85.734,68.70,183.81,100
+Helena,2.584,0.1412,65.84,350.74,348.31,101
+Miriam,2.663,0.2511,82.595,117.99,147.16,102
+Hera,2.703,0.0792,83.908,216.40,189.04,103
+Klymene,3.147,0.1613,136.553,95.05,31.70,104
+Artemis,2.374,0.1776,94.864,75.70,57.27,105
+Dione,3.18,0.1593,207.869,37.30,331.31,106
+Camilla,3.488,0.0650,210.370,118.56,305.68,107
+Hecuba,3.248,0.0574,75.498,139.01,210.23,108
+Felicitas,2.695,0.2995,82.588,114.65,57.59,109
+Lydia,2.732,0.0802,86.09,66.29,282.00,110
+Ate,2.593,0.1025,126.344,300.55,168.17,111
+Iphigenia,2.433,0.1284,69.818,328.54,17.33,112
+Amalthea,2.376,0.0862,50.137,45.18,78.63,113
+Kassandra,2.676,0.1380,94.178,286.43,352.75,114
+Thyra,2.38,0.1932,79.83,285.60,96.87,115
+Sirona,2.766,0.1415,71.70,76.63,94.27,116
+Lomia,2.991,0.0241,208.974,339.88,50.93,117
+Peitho,2.436,0.1646,40.211,209.55,33.18,118
+Althaea,2.581,0.0813,57.30,228.52,171.45,119
+Lachesis,3.117,0.0515,155.132,52.70,234.25,120
+Hermione,3.454,0.1263,209.00,13.21,296.80,121
+Gerda,3.223,0.0307,70.676,144.69,321.05,122
+Brunhild,2.694,0.1209,45.209,182.99,125.45,123
+Alkeste,2.632,0.0766,88.648,84.63,62.61,124
+Liberatrix,2.744,0.0783,48.418,20.67,110.34,125
+Velleda,2.439,0.1055,44.82,100.19,327.99,126
+Johanna,2.754,0.0666,122,140.36,93.12,127
+Nemesis,2.749,0.1281,162.515,288.58,303.46,128
+Antigone,2.867,0.2130,113,143.16,110.83,129
+Elektra,3.127,0.2093,180.652,124.07,237.62,130
+Vala,2.433,0.0675,31.337,88.46,161.23,131
+Aethra,2.61,0.3889,42.87,146.28,255.34,132
+Cyrene,3.064,0.1348,72.175,323.13,290.25,133
+Sophrosyne,2.563,0.1146,108,349.52,85.34,134
+Hertha,2.429,0.2069,79.24,238.35,340.31,135
+Austria,2.287,0.0847,36.893,142.31,132.55,136
+Meliboea,3.126,0.2117,128.678,217.38,107.53,137
+Tolosa,2.449,0.1623,52.905,142.97,260.57,138
+Juewa,2.783,0.1739,151.116,124.98,165.82,139
+Siwa,2.734,0.2141,109.79,276.34,196.95,140
+Lumen,2.665,0.2136,117.916,25.99,57.64,141
+Polana,2.419,0.1346,54.812,305.32,291.72,142
+Adria,2.762,0.0736,95.377,296.18,252.15,143
+Vibilia,2.654,0.2354,142.38,235.13,294.65,144
+Adeona,2.671,0.1464,127.783,323.38,45.25,145
+Lucina,2.719,0.0665,160.310,279.42,145.54,146
+Protogeneia,3.135,0.0231,132.93,86.65,101.77,147
+Gallia,2.77,0.1879,97.75,217.82,252.66,148
+Nuwa,2.985,0.1236,119.128,158.16,153.75,150
+Abundantia,2.591,0.0353,39.037,251.83,133.36,151
+Atala,3.14,0.0815,58.964,47.70,59.00,152
+Hilda,3.977,0.1400,170.63,299.21,39.33,153
+Bertha,3.198,0.0765,192.611,108.35,161.39,154
+Scylla,2.762,0.2727,39.605,303.47,46.59,155
+Xanthippe,2.728,0.2264,143.346,340.51,338.28,156
+Koronis,2.869,0.0526,39.025,56.81,146.61,158
+Aemilia,3.108,0.1045,125.236,214.84,333.15,159
+Una,2.726,0.0673,81.24,223.32,51.75,160
+Athor,2.38,0.1371,40.992,166.14,294.79,161
+Laurentia,3.016,0.1819,97.021,316.79,115.78,162
+Erigone,2.366,0.1922,81.579,100.94,298.65,163
+Eva,2.631,0.3473,100.254,321.19,284.04,164
+Loreley,3.123,0.0845,180.083,124.97,345.04,165
+Rhodope,2.687,0.2115,52.393,323.61,263.98,166
+Urda,2.852,0.0378,39.935,90.86,128.67,167
+Sibylla,3.376,0.0745,145.366,127.68,175.74,168
+Zelia,2.358,0.1309,37.517,74.23,334.68,169
+Maria,2.554,0.0629,33.136,212.51,157.94,170
+Ophelia,3.132,0.1321,130.808,8.24,55.72,171
+Baucis,2.38,0.1149,62.43,351.96,359.66,172
+Ino,2.741,0.2096,125.821,251.09,228.84,173
+Phaedra,2.861,0.1410,64.849,17.29,289.71,174
+Andromache,3.185,0.2330,94.532,23.32,319.79,175
+Iduna,3.182,0.1714,106.976,151.93,188.60,176
+Irma,2.772,0.2340,69.049,108.42,39.44,177
+Belisana,2.461,0.0424,35.81,271.53,211.55,178
+Klytaemnestra,2.973,0.1101,69.946,103.14,104.03,179
+Eucharis,3.127,0.2073,115.383,29.01,318.88,181
+Elsa,2.415,0.1869,39.520,184.66,310.76,182
+Istria,2.794,0.3483,32.927,357.52,263.95,183
+Dejopeja,3.187,0.0654,62.483,104.59,210.73,184
+Eunike,2.738,0.1274,160.464,43.00,223.58,185
+Celuta,2.362,0.1499,49.99,98.60,315.42,186
+Lamberta,2.729,0.2408,147.294,295.27,196.75,187
+Menippe,2.761,0.1796,35.752,56.52,69.91,188
+Phthia,2.451,0.0358,38.490,130.03,168.86,189
+Ismene,3.991,0.1676,159,23.14,271.06,190
+Kolga,2.895,0.0878,94.536,7.35,226.07,191
+Nausikaa,2.402,0.2458,98.776,262.76,30.69,192
+Ambrosia,2.6,0.2975,26.302,80.29,82.52,193
+Prokne,2.616,0.2377,161.667,148.50,163.11,194
+Eurykleia,2.876,0.0430,93.109,158.78,117.88,195
+Philomela,3.115,0.0154,144.626,268.38,202.45,196
+Arete,2.738,0.1636,31.729,95.92,245.88,197
+Ampella,2.458,0.2277,54.323,281.65,89.22,198
+Byblis,3.167,0.1819,76.129,76.50,180.06,199
+Dynamene,2.738,0.1325,128.301,83.90,86.87,200
+Penelope,2.68,0.1792,85.877,169.01,180.91,201
+Chryseis,3.071,0.1041,86.15,19.02,359.94,202
+Pompeja,2.738,0.0592,124.592,120.01,59.95,203
+Kallisto,2.671,0.1737,48.566,322.11,55.42,204
+Martha,2.776,0.0368,76.983,265.85,175.81,205
+Hersilia,2.741,0.0392,113,60.34,302.77,206
+Hedda,2.284,0.0297,57.880,246.44,192.62,207
+Lacrimosa,2.895,0.0105,40.056,237.11,121.40,208
+Dido,3.148,0.0556,179.008,303.32,249.74,209
+Isabella,2.72,0.1242,86.65,232.83,14.65,210
+Isolda,3.051,0.1571,141.125,272.16,173.00,211
+Medea,3.116,0.1026,136.12,22.19,105.10,212
+Lilaea,2.754,0.1444,82.096,270.92,162.39,213
+Oenone,2.767,0.0339,35.210,157.84,317.42,215
+Kleopatra,2.793,0.2514,122,282.10,179.89,216
+Eudora,2.867,0.3107,65.392,35.37,155.21,217
+Bianca,2.668,0.1169,60.62,263.29,62.52,218
+Thusnelda,2.354,0.2233,37.674,64.00,142.63,219
+Stephania,2.348,0.2577,31.738,317.05,78.70,220
+Eos,3.01,0.1023,95.469,85.16,192.33,221
+Lucia,3.141,0.1309,55.350,342.35,181.67,222
+Rosa,3.09,0.1197,79.806,307.84,65.37,223
+Oceana,2.645,0.0451,58.236,100.66,283.21,224
+Henrietta,3.392,0.2631,95.934,115.28,103.81,225
+Weringia,2.711,0.2042,31.494,96.38,153.90,226
+Philosophia,3.165,0.1912,123.891,60.91,267.67,227
+Adelinda,3.424,0.1377,105.912,31.37,309.30,229
+Athamantis,2.382,0.0621,111.332,291.76,139.69,230
+Vindobona,2.925,0.1523,73.545,46.33,269.25,231
+Russia,2.553,0.1745,54.730,337.37,51.89,232
+Asterope,2.66,0.0996,99.672,231.65,126.36,233
+Barbara,2.386,0.2451,45.476,192.04,192.29,234
+Carolina,2.882,0.0614,57.517,222.40,208.00,235
+Honoria,2.799,0.1912,77.708,356.32,174.32,236
+Coelestina,2.762,0.0710,41.08,321.10,200.56,237
+Hypatia,2.905,0.0904,155.659,207.96,210.57,238
+Adrastea,2.965,0.2360,37.609,259.76,209.90,239
+Vanadis,2.664,0.2083,87.928,152.73,300.93,240
+Germania,3.047,0.1038,168.90,288.28,80.58,241
+Kriemhild,2.862,0.1219,40.802,38.73,279.12,242
+Ida,2.862,0.0438,32,83.13,113.94,243
+Vera,3.098,0.1972,75.949,119.88,331.68,245
+Asporina,2.695,0.1090,50.891,258.71,96.19,246
+Eukrate,2.741,0.2457,130.935,149.73,55.33,247
+Lameia,2.471,0.0661,50.120,50.89,11.68,248
+Ilse,2.377,0.2172,34.83,42.08,42.07,249
+Bettina,3.145,0.1358,120.995,51.14,75.87,250
+Sophia,3.099,0.0937,27.495,298.52,288.52,251
+Clementina,3.162,0.0664,65.344,117.95,159.63,252
+Mathilde,2.648,0.2635,52.8,267.13,157.82,253
+Oppavia,2.747,0.0790,56.939,335.38,155.02,255
+Walpurga,2.999,0.0653,66.634,10.53,47.51,256
+Silesia,3.118,0.1119,72.66,24.03,31.65,257
+Tyche,2.614,0.2049,64.78,263.12,155.67,258
+Aletheia,3.131,0.1299,174.318,138.85,166.89,259
+Huberta,3.447,0.1082,101.539,59.66,179.92,260
+Prymno,2.331,0.0896,50.011,228.42,66.78,261
+Libussa,2.8,0.1368,62.969,317.24,339.95,264
+Aline,2.806,0.1541,109.494,111.21,151.78,266
+Tirza,2.775,0.0992,55.998,33.53,197.11,267
+Adorea,3.094,0.1368,144.585,305.94,68.44,268
+Justitia,2.616,0.2129,50.728,325.22,119.73,269
+Anahita,2.198,0.1503,51.400,104.05,80.52,270
+Penthesilea,3.003,0.1044,65.901,263.36,57.55,271
+Antonia,2.778,0.0287,26.870,8.89,68.88,272
+Atropos,2.395,0.1599,29.768,299.54,121.18,273
+Philagoria,3.043,0.1188,27.307,55.99,119.97,274
+Sapientia,2.771,0.1635,103,9.00,39.46,275
+Adelheid,3.12,0.0657,114.723,203.31,265.10,276
+Elvira,2.885,0.0927,30.422,309.73,136.64,277
+Paulina,2.759,0.1317,32.773,114.68,140.52,278
+Thule,4.265,0.0437,126.59,300.08,26.66,279
+Philia,2.942,0.1103,45.69,84.07,89.27,280
+Clorinde,2.339,0.0812,39.03,107.38,296.87,282
+Emma,3.05,0.1444,132.385,135.64,55.49,283
+Amalia,2.359,0.2217,52.95,184.31,58.01,284
+Regina,3.088,0.2045,47.156,141.11,14.42,285
+Iclea,3.192,0.0243,94.30,38.39,209.61,286
+Nephthys,2.353,0.0227,59.615,313.18,119.75,287
+Glauke,2.759,0.2058,28.981,246.35,84.55,288
+Nenetta,2.877,0.2016,37.586,146.83,190.55,289
+Ludovica,2.53,0.0330,30.864,157.65,286.11,292
+Brasilia,2.862,0.1051,57.486,155.20,87.08,293
+Felicia,3.157,0.2332,51.865,205.50,186.19,294
+Theresia,2.797,0.1675,28.340,328.05,148.21,295
+Caecilia,3.166,0.1397,39.48,107.54,353.51,297
+Geraldina,3.205,0.0579,67.373,297.91,324.10,300
+Bavaria,2.725,0.0666,53.042,195.76,124.01,301
+Clarissa,2.406,0.1100,38.53,21.64,55.03,302
+Josephina,3.122,0.0565,124.923,351.31,67.04,303
+Olga,2.404,0.2216,65.990,232.67,172.46,304
+Gordonia,3.091,0.1961,47.739,46.55,260.70,305
+Unitas,2.358,0.1507,47.200,273.31,168.05,306
+Nike,2.905,0.1438,61.313,208.97,324.19,307
+Polyxo,2.749,0.0395,128.578,146.00,112.42,308
+Fraternitas,2.665,0.1137,41.075,282.63,311.08,309
+Margarita,2.76,0.1164,33.708,206.93,325.09,310
+Claudia,2.896,0.0053,26.300,268.20,82.92,311
+Pierretta,2.781,0.1605,46.191,107.52,262.32,312
+Chaldaea,2.375,0.1821,71.183,80.99,315.89,313
+Rosalia,3.159,0.1714,60.689,106.66,191.64,314
+Goberta,3.185,0.1282,56.067,300.24,316.99,316
+Magdalena,3.193,0.0847,85,144.91,295.61,318
+Leona,3.408,0.2160,49.943,273.14,227.79,319
+Florentina,2.884,0.0472,27.974,165.22,35.33,321
+Phaeo,2.782,0.2448,69.855,48.21,114.69,322
+Brucia,2.382,0.2994,27.714,175.03,291.54,323
+Bamberga,2.681,0.3414,220.691,314.55,44.21,324
+Heidelberga,3.215,0.1512,75.72,347.27,70.60,325
+Tamara,2.318,0.1899,93.00,225.02,238.52,326
+Columbia,2.776,0.0610,30.291,277.72,307.88,327
+Gudrun,3.107,0.1069,145.680,321.43,107.18,328
+Svea,2.477,0.0243,81.057,68.05,56.13,329
+Etheridgea,3.026,0.0961,74.92,102.41,333.78,331
+Siri,2.773,0.0883,40.37,251.35,297.91,332
+Badenia,3.133,0.1599,72.199,126.57,22.96,333
+Chicago,3.889,0.0242,198.770,4.30,151.16,334
+Roberta,2.475,0.1727,97.109,141.82,139.83,335
+Lacadiera,2.252,0.0956,63.356,187.74,31.01,336
+Devosa,2.383,0.1362,64.549,344.57,99.43,337
+Budrosa,2.913,0.0188,50.506,340.93,108.53,338
+Dorothea,3.01,0.0986,44.329,288.34,164.68,339
+Eduarda,2.747,0.1167,28.025,95.11,43.13,340
+Endymion,2.568,0.1299,64.266,94.30,225.00,342
+Desiderata,2.597,0.3140,124.181,52.01,237.60,344
+Tercidina,2.325,0.0618,90.243,123.68,231.15,345
+Hermentaria,2.795,0.1027,86.447,250.51,291.91,346
+Pariana,2.612,0.1657,48.615,115.25,86.26,347
+May,2.97,0.0711,82.82,46.87,13.59,348
+Dembowska,2.926,0.0905,139.77,342.96,344.48,349
+Ornamenta,3.108,0.1599,128.729,177.15,337.79,350
+Yrsa,2.765,0.1558,39.720,347.99,31.81,351
+Gisela,2.195,0.1498,26.744,320.98,144.40,352
+Eleonora,2.803,0.1121,148.970,183.83,6.39,354
+Liguria,2.756,0.2409,145.503,98.73,79.38,356
+Ninina,3.152,0.0772,124.107,135.43,255.54,357
+Apollonia,2.875,0.1531,90.116,224.10,252.78,358
+Georgia,2.728,0.1570,43.89,42.15,337.85,359
+Carlova,3.003,0.1734,129.125,6.91,289.86,360
+Bononia,3.965,0.2108,154.334,219.72,68.34,361
+Havnia,2.579,0.0443,98,156.67,31.45,362
+Padua,2.746,0.0719,97,265.82,296.32,363
+Isara,2.221,0.1487,25.901,78.37,313.13,364
+Corduba,2.804,0.1571,86.773,294.95,215.71,365
+Vincentina,3.144,0.0566,86.368,275.69,333.58,366
+Haidea,3.073,0.2013,69.277,275.36,95.42,368
+Aeria,2.649,0.0970,73.767,210.10,269.79,369
+Modestia,2.324,0.0909,38.093,46.04,68.22,370
+Bohemia,2.727,0.0635,52.976,222.47,342.16,371
+Palma,3.163,0.2546,173.642,268.38,115.23,372
+Melusina,3.122,0.1380,98.695,123.96,348.91,373
+Burgundia,2.779,0.0790,44.67,359.99,25.77,374
+Ursula,3.125,0.1036,216,115.26,341.44,375
+Geometria,2.288,0.1727,35.465,112.53,316.76,376
+Campania,2.69,0.0754,90.346,0.02,196.08,377
+Holmia,2.776,0.1308,27.831,278.77,157.26,378
+Huenna,3.143,0.1799,84.787,119.24,180.72,379
+Fiducia,2.679,0.1128,67.508,200.90,240.01,380
+Myrrha,3.223,0.0899,127.639,330.07,144.02,381
+Dodona,3.121,0.1709,65.209,3.36,270.39,382
+Janina,3.14,0.1681,43.482,68.38,324.56,383
+Burdigala,2.655,0.1464,34.435,270.29,34.64,384
+Ilmatar,2.848,0.1256,85.837,214.95,189.06,385
+Siegena,2.899,0.1690,165.01,105.03,220.78,386
+Aquitania,2.74,0.2349,100.51,318.15,157.45,387
+Charybdis,3.007,0.0663,125.754,31.93,330.44,388
+Industria,2.608,0.0665,74.378,96.86,265.07,389
+Alma,2.653,0.1311,25.688,231.91,191.56,390
+Wilhelmina,2.884,0.1391,60.750,5.30,173.45,392
+Lampetia,2.781,0.3302,116.191,238.62,90.82,393
+Arduina,2.762,0.2275,29.970,299.82,271.31,394
+Delia,2.785,0.0846,44.189,277.52,11.13,395
+Aeolia,2.74,0.1601,39.242,156.63,21.42,396
+Vienna,2.634,0.2482,49.032,303.26,140.07,397
+Admete,2.738,0.2237,49.771,27.22,160.54,398
+Persephone,3.05,0.0763,39.566,266.12,192.98,399
+Ducrosa,3.128,0.1158,36.001,291.95,237.30,400
+Ottilia,3.346,0.0317,87.803,128.63,300.89,401
+Chloe,2.559,0.1123,55.421,25.20,17.34,402
+Cyane,2.81,0.0981,53.574,49.80,254.52,403
+Arsinoe,2.593,0.2003,94.970,153.02,120.66,404
+Thia,2.584,0.2434,108.894,241.86,308.72,405
+Erna,2.918,0.1783,46.266,125.08,37.65,406
+Arachne,2.624,0.0705,95.07,258.24,82.42,407
+Fama,3.166,0.1455,35.620,138.88,108.57,408
+Aspasia,2.575,0.0719,171.012,17.36,353.57,409
+Chloris,2.724,0.2414,118.929,204.53,172.82,410
+Xanthe,2.935,0.1151,76.53,202.67,181.32,411
+Elisabetha,2.762,0.0419,96.056,70.22,91.86,412
+Edburga,2.585,0.3416,34.242,197.54,252.88,413
+Liriope,3.507,0.0732,88.760,121.14,318.42,414
+Palatia,2.793,0.3000,83.560,54.92,299.09,415
+Vaticana,2.792,0.2176,85.47,330.38,198.29,416
+Suevia,2.8,0.1356,54.874,325.70,348.57,417
+Alemannia,2.594,0.1195,40.330,345.64,125.92,418
+Aurelia,2.598,0.2514,148.701,48.45,44.65,419
+Bertholda,3.414,0.0290,138.699,173.60,234.85,420
+Diotima,3.069,0.0351,175.859,244.94,199.40,423
+Gratia,2.774,0.1089,102.565,54.71,333.83,424
+Cornelia,2.886,0.0589,67.925,107.01,121.97,425
+Hippo,2.888,0.1058,137.562,289.83,221.81,426
+Galene,2.971,0.1198,32.193,116.14,11.19,427
+Lotis,2.607,0.1236,69.62,196.03,169.17,429
+Hybris,2.85,0.2505,31.702,323.44,179.25,430
+Nephele,3.14,0.1706,101.900,223.72,217.20,431
+Pythia,2.369,0.1462,46.90,185.14,173.87,432
+Ella,2.449,0.1551,34.792,60.11,333.25,435
+Patricia,3.201,0.0694,58.609,166.35,41.05,436
+Zeuxo,2.554,0.0682,58.871,207.46,210.38,438
+Ohio,3.133,0.0663,70.421,27.94,244.49,439
+Bathilde,2.807,0.0812,65.131,46.08,202.95,441
+Eichsfeldia,2.345,0.0703,62.171,15.28,84.56,442
+Photographica,2.215,0.0405,25.504,87.55,348.68,443
+Gyptis,2.77,0.1743,159.331,80.00,154.56,444
+Edna,3.198,0.1975,87.812,174.48,81.66,445
+Aeternitas,2.788,0.1256,53.562,147.56,279.06,446
+Valentine,2.984,0.0452,85.224,241.78,321.41,447
+Natalie,3.135,0.1883,50.534,24.11,293.55,448
+Hamburga,2.552,0.1728,85.59,254.28,48.54,449
+Brigitta,3.019,0.0976,37.038,138.67,359.11,450
+Patientia,3.067,0.0717,253.900,288.40,335.86,451
+Mathesis,2.626,0.1114,81.743,200.67,177.46,454
+Bruchsalia,2.655,0.2951,88.792,315.18,273.52,455
+Abnoba,2.789,0.1789,37.713,64.47,7.17,456
+Hercynia,2.994,0.2424,36.698,122.52,277.15,458
+Signe,2.619,0.2112,25.784,194.64,19.49,459
+Saskia,3.116,0.1449,43.603,318.62,308.56,461
+Eriphyla,2.876,0.0887,34.274,346.93,250.07,462
+Megaira,2.801,0.2050,77.056,19.80,257.86,464
+Alekto,3.093,0.2054,73.34,10.09,284.11,465
+Tisiphone,3.365,0.0936,95.495,155.70,253.47,466
+Laura,2.945,0.1064,39.471,32.62,94.02,467
+Lina,3.133,0.1963,60.238,24.93,332.24,468
+Argentina,3.193,0.1583,133.718,138.29,211.60,469
+Kilia,2.406,0.0947,27.750,127.04,47.81,470
+Papagena,2.89,0.2287,148.128,86.07,315.63,471
+Roma,2.544,0.0950,50.278,138.93,296.51,472
+Prudentia,2.453,0.2109,40.972,9.64,156.13,474
+Hedwig,2.65,0.0730,138.493,13.08,1.40,476
+Tergeste,3.021,0.0806,80.738,250.00,242.21,478
+Caprera,2.721,0.2189,60.088,281.24,269.49,479
+Hansa,2.643,0.0462,56.22,185.05,213.25,480
+Emita,2.739,0.1579,101.829,216.07,349.42,481
+Petrina,3,0.0968,45.751,305.57,87.73,482
+Seppina,3.426,0.0511,66.858,158.08,162.99,483
+Pittsburghia,2.667,0.0579,30.060,79.04,189.55,484
+Genua,2.748,0.1918,63.88,190.98,272.21,485
+Venetia,2.67,0.0861,59.046,54.33,281.16,487
+Kreusa,3.182,0.1570,168.117,184.03,74.26,488
+Comacina,3.151,0.0479,139.39,277.69,9.22,489
+Veritas,3.172,0.0897,118.803,21.14,193.25,490
+Carina,3.195,0.0864,91.176,283.29,231.63,491
+Gismonda,3.112,0.1791,53.418,266.15,296.82,492
+Griseldis,3.115,0.1766,41.550,191.78,46.81,493
+Virtus,2.984,0.0647,100.786,167.95,215.66,494
+Eulalia,2.488,0.1289,37.287,146.99,207.86,495
+Iva,2.849,0.3013,40.932,291.81,3.54,497
+Tokio,2.651,0.2232,81.83,274.30,241.90,498
+Venusia,4.011,0.2169,77.328,35.20,174.82,499
+Selinur,2.614,0.1440,40.828,149.39,74.94,500
+Urhixidur,3.164,0.1416,74.457,190.02,356.28,501
+Evelyn,2.722,0.1758,81.68,177.44,41.66,503
+Cora,2.723,0.2153,30.438,181.40,248.36,504
+Cava,2.688,0.2430,115,308.02,336.88,505
+Marion,3.039,0.1470,105.94,190.61,145.68,506
+Laodica,3.153,0.1013,45.170,181.45,100.43,507
+Princetonia,3.16,0.0077,117.241,3.93,206.85,508
+Iolanda,3.061,0.0964,51.892,258.03,157.46,509
+Mabella,2.611,0.1909,60.450,17.16,91.19,510
+Davida,3.162,0.1884,270.327,149.38,337.16,511
+Centesima,3.013,0.0847,48.805,164.15,225.78,513
+Armida,3.046,0.0374,120.093,59.57,110.78,514
+Athalia,3.122,0.1762,41.190,104.65,300.27,515
+Amherstia,2.681,0.2734,65.144,114.93,258.14,516
+Edith,3.155,0.1794,111.890,32.08,143.55,517
+Sylvania,2.792,0.1831,40.078,166.25,302.76,519
+Franziska,3.003,0.1105,25.261,234.99,21.11,520
+Brixia,2.743,0.2783,107.227,23.05,316.03,521
+Helga,3.628,0.0867,101.22,123.54,248.73,522
+Ada,2.967,0.1790,31.89,56.77,189.93,523
+Fidelio,2.637,0.1280,65.527,297.23,79.23,524
+Jena,3.125,0.1320,44.840,171.91,357.69,526
+Euryanthe,2.725,0.1509,52.627,322.64,204.14,527
+Rezia,3.397,0.0219,91.966,79.40,350.85,528
+Preziosa,3.021,0.0947,32.01,316.82,331.99,529
+Turandot,3.187,0.2182,84.85,79.39,199.46,530
+Herculina,2.771,0.1788,167.791,197.17,76.63,532
+Sara,2.981,0.0445,30.819,316.81,32.39,533
+Nassovia,2.883,0.0592,32.333,146.47,338.36,534
+Montague,2.569,0.0253,79.299,279.77,68.53,535
+Merapi,3.496,0.0874,147.066,243.65,295.73,536
+Pauly,3.073,0.2291,40.732,302.02,187.59,537
+Friederike,3.156,0.1708,70.640,266.65,227.56,538
+Pamina,2.737,0.2140,68.356,291.67,97.42,539
+Deborah,2.814,0.0497,60.147,3.33,359.43,541
+Susanna,2.905,0.1422,42.117,234.56,216.84,542
+Charlotte,3.064,0.1531,45.613,300.84,108.44,543
+Jetta,2.591,0.1532,27.169,118.19,343.07,544
+Messalina,3.201,0.1700,112.631,288.83,331.18,545
+Herodias,2.597,0.1153,65.945,258.84,110.07,546
+Praxedis,2.775,0.2353,52.462,141.85,196.52,547
+Senta,2.588,0.2229,37.434,131.13,45.12,550
+Ortrud,2.967,0.1185,81.113,329.65,70.47,551
+Sigelinde,3.147,0.0900,88.697,149.61,346.41,552
+Peraga,2.375,0.1519,95.87,33.90,127.69,554
+Norma,3.181,0.1546,31.040,255.88,0.56,555
+Phyllis,2.464,0.1043,36.279,90.15,177.85,556
+Carmen,2.912,0.0395,54.811,254.21,311.77,558
+Nanon,2.711,0.0651,79.82,10.36,128.97,559
+Delila,2.755,0.1578,35.334,258.36,4.74,560
+Ingwelde,3.169,0.1221,31.562,312.48,318.31,561
+Salome,3.018,0.1022,32.651,329.92,263.61,562
+Suleika,2.711,0.2364,53.29,185.78,336.80,563
+Dudu,2.747,0.2769,52.010,179.99,214.92,564
+Marbachia,2.442,0.1311,27.332,268.36,292.37,565
+Stereoskopia,3.379,0.1202,167.381,133.61,299.75,566
+Eleutheria,3.133,0.0896,93.41,56.10,133.67,567
+Cheruskia,2.88,0.1686,71.224,207.59,173.93,568
+Misa,2.658,0.1806,72.95,227.34,142.51,569
+Kythera,3.42,0.1188,87.486,70.70,161.68,570
+Rebekka,2.401,0.1564,28.903,82.85,192.11,572
+Recha,3.014,0.1101,47.582,71.67,29.70,573
+Emanuela,2.99,0.1919,74.378,208.94,27.23,576
+Rhea,3.11,0.1548,38.234,105.47,329.85,577
+Happelia,2.752,0.1921,69.29,272.38,261.46,578
+Sidonia,3.014,0.0773,85.57,177.99,228.85,579
+Selene,3.228,0.0872,48.204,20.59,338.65,580
+Tauntonia,3.213,0.0343,61.481,10.44,25.26,581
+Olympia,2.61,0.2219,44.347,195.17,310.24,582
+Klotilde,3.171,0.1600,78.236,77.96,252.03,583
+Semiramis,2.374,0.2340,54.01,345.27,85.29,584
+Bilkis,2.432,0.1281,49.761,219.65,329.83,585
+Thekla,3.04,0.0642,95.203,327.48,253.25,586
+Achilles,5.209,0.1480,130.099,321.40,133.50,588
+Croatia,3.136,0.0400,93.617,81.81,228.11,589
+Tomyris,2.997,0.0804,30.577,187.28,338.67,590
+Irmgard,2.684,0.2068,51.86,131.79,217.90,591
+Bathseba,3.023,0.1338,43.787,106.90,257.50,592
+Titania,2.698,0.2170,70.145,91.27,30.91,593
+Polyxena,3.206,0.0638,90.647,337.44,280.00,595
+Scheila,2.929,0.1626,159.726,335.51,175.50,596
+Bandusia,2.671,0.1444,36.06,69.43,307.06,597
+Octavia,2.76,0.2509,78.237,233.21,292.12,598
+Luisa,2.772,0.2926,70.249,298.82,294.38,599
+Musa,2.66,0.0554,25.115,243.62,113.04,600
+Nerthus,3.133,0.1043,75.535,259.90,160.47,601
+Marianna,3.082,0.2511,110.444,239.80,45.82,602
+Tekmessa,3.154,0.1929,64.536,344.47,28.55,604
+Juvisia,3.002,0.1365,69.86,111.95,15.22,605
+Brangane,2.586,0.2210,35.758,248.17,58.39,606
+Jenny,2.857,0.0748,67.520,123.52,292.18,607
+Fulvia,3.086,0.0393,54.17,182.78,108.86,609
+Valeria,2.979,0.1231,57.468,95.56,256.60,611
+Veronika,3.154,0.2592,38.767,254.26,122.51,612
+Ginevra,2.919,0.0561,81.344,6.37,65.68,613
+Pia,2.693,0.1082,29.191,352.02,209.82,614
+Roswitha,2.631,0.1107,48.626,119.72,247.01,615
+Patroclus,5.211,0.1397,140.362,286.55,308.08,617
+Elfriede,3.191,0.0695,131.292,126.38,229.72,618
+Triberga,2.521,0.0757,29.051,321.97,178.02,619
+Werdandi,3.125,0.1363,29.726,291.28,36.47,621
+Chimaera,2.461,0.1111,44.09,336.34,124.64,623
+Hektor,5.267,0.0226,225,254.22,181.56,624
+Xenia,2.644,0.2282,28.287,72.37,200.44,625
+Notburga,2.574,0.2418,73.236,34.86,43.42,626
+Charis,2.9,0.0586,38.018,277.05,177.80,627
+Christine,2.581,0.0437,48.239,82.62,205.12,628
+Bernardina,3.13,0.1598,35.087,283.85,38.22,629
+Philippina,2.791,0.0839,50.491,278.45,279.45,631
+Zelima,3.019,0.0841,33.387,228.53,190.40,633
+Ute,3.05,0.1813,74.017,106.72,220.79,634
+Vundtia,3.143,0.0782,94.415,70.20,228.19,635
+Erika,2.913,0.1694,73.147,218.15,298.70,636
+Moira,2.734,0.1610,59.594,130.20,128.77,638
+Latona,3.015,0.1076,78.509,269.88,70.86,639
+Brambilla,3.159,0.0792,62.667,188.80,29.36,640
+Clara,3.184,0.1277,33.36,290.47,120.87,642
+Scheherezade,3.359,0.0567,64.997,123.71,229.51,643
+Agrippina,3.215,0.1393,28.916,300.32,88.44,645
+Pippa,3.194,0.2022,68.27,308.48,180.75,648
+Antikleia,3.021,0.1014,31.895,268.81,354.09,651
+Berenike,3.017,0.0426,49.793,167.34,60.68,653
+Zelinda,2.298,0.2308,160.736,257.52,214.48,654
+Briseis,2.989,0.0836,29.057,26.64,281.40,655
+Beagle,3.148,0.1331,62.604,88.38,330.49,656
+Gunlod,2.611,0.1134,39.401,314.71,244.75,657
+Nestor,5.166,0.1172,112.320,64.97,343.85,659
+Crescentia,2.534,0.1074,42.302,314.44,105.93,660
+Cloelia,3.013,0.0378,40.081,262.16,183.97,661
+Gerlinde,3.074,0.1452,107.795,141.28,312.33,663
+Judith,3.194,0.2309,85.214,12.83,102.53,664
+Sabine,3.141,0.1725,51.09,144.41,318.22,665
+Desdemona,2.594,0.2366,32.741,15.09,173.88,666
+Denise,3.183,0.1898,88.630,193.29,305.51,667
+Kypria,3.012,0.0759,29.227,293.23,116.30,669
+Ottegebe,2.803,0.1924,35.886,34.37,194.76,670
+Carnegia,3.093,0.0659,60.604,213.01,89.99,671
+Astarte,2.555,0.1342,35.584,321.20,309.15,672
+Edda,2.817,0.0087,37.622,249.28,243.51,673
+Rachele,2.921,0.1950,96.171,182.65,41.65,674
+Ludmilla,2.768,0.2043,76,166.44,152.63,675
+Melitta,3.064,0.1220,78.369,216.74,184.90,676
+Aaltje,2.955,0.0497,32.403,18.53,275.33,677
+Fredegundis,2.572,0.2200,39.585,190.40,121.20,678
+Pax,2.588,0.3095,63.909,146.83,267.01,679
+Genoveva,3.144,0.2949,83.92,16.74,245.95,680
+Lanzia,3.114,0.0582,83.04,280.24,281.01,683
+Gersuind,2.589,0.2685,55.258,348.96,89.15,686
+Melanie,2.698,0.1389,41.614,153.98,139.11,688
+Wratislavia,3.149,0.1769,134.65,46.91,114.34,690
+Lehigh,3.01,0.1237,79.451,206.86,304.25,691
+Hippodamia,3.384,0.1686,42.771,104.26,53.78,692
+Zerbinetta,2.943,0.0307,82.114,175.58,284.50,693
+Ekard,2.67,0.3230,121.891,291.91,111.88,694
+Bella,2.539,0.1604,40.620,310.46,80.00,695
+Leonora,3.174,0.2498,81.580,297.57,103.51,696
+Galilea,2.882,0.1541,80.14,106.00,333.08,697
+Ernestina,2.868,0.1110,27.037,31.94,98.44,698
+Oriola,3.012,0.0372,42.943,190.87,325.74,701
+Alauda,3.195,0.0165,190.980,224.15,353.26,702
+Interamnia,3.056,0.1555,306.313,285.27,94.80,704
+Erminia,2.924,0.0508,132.261,22.16,102.40,705
+Hirundo,2.728,0.1950,30.819,255.61,31.17,706
+Fringilla,2.915,0.1132,95.173,250.52,19.49,709
+Gertrud,3.132,0.1322,29.208,298.81,99.64,710
+Boliviana,2.576,0.1852,124.125,336.28,181.39,712
+Luscinia,3.399,0.1554,97.968,87.16,138.39,713
+Ulula,2.536,0.0555,41.343,256.68,232.19,714
+Transvaalia,2.767,0.0836,25.458,258.86,301.28,715
+Wisibada,3.137,0.2640,27.656,257.17,24.46,717
+Erida,3.056,0.1983,70.911,13.74,174.57,718
+Bohlinia,2.888,0.0185,33.73,39.79,110.93,720
+Tabora,3.553,0.1175,86.309,153.63,352.58,721
+Joella,2.565,0.2856,44.02,323.00,113.23,726
+Nipponia,2.567,0.1042,32.17,330.83,274.21,727
+Watsonia,2.76,0.0969,50.025,293.98,87.51,729
+Sorga,2.986,0.1417,34.597,315.50,288.76,731
+Tjilaki,2.456,0.0449,29.791,154.00,64.26,732
+Mocia,3.4,0.0583,98.493,13.75,189.29,733
+Benda,3.146,0.1004,67.318,158.06,65.94,734
+Marghanna,2.731,0.3209,67.976,117.76,309.87,735
+Arequipa,2.591,0.2448,47.804,137.95,134.21,737
+Alagasta,3.044,0.0537,62.79,154.84,45.83,738
+Mandeville,2.738,0.1435,104.517,352.48,44.99,739
+Cantabia,3.055,0.1085,90.90,142.67,48.76,740
+Botolphia,2.718,0.0698,29.64,89.29,61.53,741
+Edisona,3.012,0.1154,47.087,82.99,283.61,742
+Eugenisis,2.792,0.0600,51.072,211.48,186.25,743
+Aguntina,3.17,0.1166,58.636,76.18,28.64,744
+Marlu,3.112,0.2365,74.274,167.97,306.97,746
+Winchester,3.001,0.3394,171.71,76.28,277.45,747
+Simeisa,3.951,0.1889,103.714,39.53,177.68,748
+Faina,2.551,0.1511,113.699,78.31,302.51,751
+Sulamitis,2.462,0.0747,60.171,147.73,23.17,752
+Malabar,2.987,0.0505,94.522,347.70,303.15,754
+Quintilla,3.179,0.1368,41.210,38.29,44.08,755
+Lilliana,3.197,0.1479,64.837,267.17,4.32,756
+Portlandia,2.374,0.1082,32.894,313.10,43.81,757
+Mancunia,3.189,0.1502,88.985,247.92,314.29,758
+Vinifera,2.619,0.2053,52.926,218.86,1.06,759
+Massinga,3.147,0.2336,71.29,282.92,200.43,760
+Pulcova,3.154,0.1067,147.343,341.41,188.78,762
+Gedania,3.192,0.0926,58.28,344.25,158.51,764
+Moguntia,3.018,0.0969,41.044,171.21,70.77,766
+Bondia,3.12,0.1828,43.039,244.19,269.23,767
+Struveana,3.138,0.2134,32.597,133.90,16.64,768
+Tatjana,3.167,0.1871,96.720,81.01,253.32,769
+Libera,2.652,0.2470,29.322,3.29,228.58,771
+Tanete,2.998,0.0944,126.473,183.23,145.94,772
+Irmintraud,2.859,0.0786,91.672,267.04,332.89,773
+Armor,3.05,0.1667,50.214,250.82,28.64,774
+Lumiere,3.018,0.0670,31.958,250.08,169.12,775
+Berbericia,2.929,0.1658,151.711,269.02,306.76,776
+Gutemberga,3.221,0.1146,71.749,180.97,264.54,777
+Theobalda,3.179,0.2559,55.317,10.91,135.04,778
+Nina,2.664,0.2273,80.572,77.61,49.00,779
+Armenia,3.118,0.0980,126.263,347.06,212.51,780
+Kartvelia,3.222,0.1191,72.927,44.21,155.62,781
+Nora,2.342,0.2296,38.719,301.71,154.81,783
+Pickeringia,3.098,0.2416,75.596,205.89,238.05,784
+Zwetana,2.569,0.2098,49.460,27.06,131.43,785
+Bredichina,3.175,0.1594,108.309,11.93,133.70,786
+Moskva,2.539,0.1298,27.927,146.29,125.78,787
+Hohensteina,3.121,0.1356,111.295,170.01,47.83,788
+Pretoria,3.413,0.1541,170.37,40.28,38.61,790
+Ani,3.124,0.1928,116.865,139.98,201.70,791
+Metcalfia,2.622,0.1315,61.804,59.52,227.36,792
+Arizona,2.795,0.1241,26.636,71.01,308.20,793
+Irenaea,3.129,0.2961,35.703,138.00,131.35,794
+Fini,2.75,0.1020,85.263,336.49,190.02,795
+Sarita,2.635,0.3201,43.580,42.21,329.48,796
+Ruth,3.014,0.0352,43.19,341.10,44.40,798
+Gudula,2.541,0.0229,47.185,260.37,236.46,799
+Helwerthia,2.606,0.0767,32.404,156.26,335.45,801
+Picka,3.196,0.0639,46.50,83.74,57.13,803
+Hispania,2.837,0.1411,137.952,329.76,344.74,804
+Hormuthia,3.193,0.1866,73.095,118.62,131.81,805
+Gyldenia,3.205,0.0805,83.103,227.22,121.45,806
+Merxia,2.745,0.1292,30.923,84.07,274.63,808
+Tauris,3.159,0.3056,102.229,352.84,296.27,814
+Juliana,3.002,0.1082,50.745,123.12,20.84,816
+Kapteynia,3.17,0.0908,64.255,29.14,291.52,818
+Adriana,3.129,0.0505,58.65,278.79,194.71,820
+Fanny,2.773,0.2116,28.856,278.51,32.86,821
+Anastasia,2.792,0.1373,32.457,148.18,141.44,824
+Lindemannia,3.193,0.0277,47.891,236.28,295.83,828
+Academia,2.581,0.0986,42.685,107.93,42.30,829
+Petropolitana,3.211,0.0656,41.328,40.17,91.00,830
+Burnhamia,3.183,0.2009,61.278,311.58,91.48,834
+Olivia,3.221,0.0880,30.418,103.89,67.36,835
+Seraphina,2.9,0.1311,58.095,134.77,117.37,838
+Zenobia,3.132,0.1026,27.306,69.65,9.55,840
+Kerstin,3.238,0.1165,43.576,91.70,352.81,842
+Leontina,3.204,0.0695,42.154,194.88,353.61,844
+Naema,2.94,0.0700,52.677,24.50,293.22,845
+Lipperta,3.131,0.1754,52.41,23.19,130.04,846
+Inna,3.112,0.1627,33.027,164.07,125.66,848
+Ara,3.146,0.2012,80.756,69.50,63.04,849
+Altona,3.004,0.1270,80.90,72.19,135.16,850
+Wladilena,2.362,0.2744,26.541,330.34,282.39,852
+Nansenia,2.312,0.1050,27.593,357.52,59.82,853
+Backlunda,2.435,0.1193,45.449,293.63,72.76,856
+Bouzareah,3.226,0.1099,65.417,57.92,21.86,859
+Ursina,2.795,0.1072,34.561,308.87,21.94,860
+Aida,3.139,0.1005,66.85,120.63,192.31,861
+Franzia,2.802,0.0827,27.033,180.14,120.69,862
+Benkoela,3.2,0.0283,38.724,34.92,97.80,863
+Fatme,3.126,0.0525,78.061,140.83,263.95,866
+Lova,2.704,0.1464,50.692,357.36,286.68,868
+Holda,2.732,0.0785,34.431,83.90,18.48,872
+Mechthild,2.627,0.1490,34.471,187.38,109.83,873
+Rotraut,3.154,0.0796,58.287,277.89,9.04,874
+Walkure,2.487,0.1592,38.41,13.63,275.66,877
+Herba,2.999,0.3235,32.329,1.23,100.79,880
+Swetlana,3.122,0.2675,42.440,258.89,126.46,882
+Priamus,5.191,0.1247,101.093,14.54,335.88,884
+Ulrike,3.095,0.1839,30.537,66.85,203.89,885
+Washingtonia,3.169,0.2710,86.793,206.47,302.23,886
+Parysatis,2.709,0.1947,44.749,147.01,298.02,888
+Waltraut,3.021,0.0599,28.376,192.44,87.75,890
+Gunhild,2.859,0.0265,55.747,353.18,293.82,891
+Seeligeria,3.228,0.1046,74.481,64.81,286.12,892
+Leopoldina,3.051,0.1464,85.992,42.74,222.49,893
+Erda,3.119,0.1104,28.309,257.22,116.61,894
+Helio,3.203,0.1442,109.568,225.88,177.56,895
+Jokaste,2.905,0.2017,31.018,268.01,127.52,899
+Nealley,3.237,0.0459,58.065,209.01,233.98,903
+Rockefellia,2.995,0.0852,49.146,290.41,253.40,904
+Repsolda,2.893,0.0860,65.752,42.13,293.51,906
+Rhoda,2.799,0.1633,82.660,309.71,88.52,907
+Buda,2.472,0.1479,30.749,149.68,23.36,908
+Ulla,3.542,0.0912,116.44,269.23,232.51,909
+Anneliese,2.925,0.1555,48.590,99.45,208.14,910
+Agamemnon,5.28,0.0672,131.038,349.86,81.04,911
+Maritima,3.129,0.1788,82.675,275.42,91.15,912
+Palisana,2.458,0.2144,76.190,222.88,49.05,914
+America,2.365,0.2366,33.23,68.03,41.57,916
+Lyka,2.381,0.2011,34.878,342.91,359.88,917
+Ilsebill,2.773,0.0838,33.500,142.72,156.24,919
+Rogeria,2.622,0.1046,26.656,300.25,270.17,920
+Jovita,3.17,0.1855,55.312,76.24,70.60,921
+Herluga,2.616,0.1944,34.553,48.09,201.36,923
+Toni,2.94,0.1533,85.49,113.07,220.17,924
+Alphonsina,2.7,0.0808,57.505,335.04,201.77,925
+Imhilde,2.981,0.1824,48.48,212.40,173.63,926
+Ratisbona,3.221,0.0911,75.892,189.07,172.32,927
+Hildrun,3.134,0.1478,62.817,115.93,21.83,928
+Westphalia,2.432,0.1429,34.922,188.22,330.14,930
+Whittemora,3.17,0.2331,45.298,85.34,315.44,931
+Hooveria,2.42,0.0910,58.978,128.58,49.97,932
+Thuringia,2.749,0.2159,53.714,43.50,64.28,934
+Kunigunde,3.132,0.1757,43.227,115.41,253.59,936
+Chlosinde,3.151,0.1958,33.466,12.08,225.34,938
+Kordula,3.368,0.1700,79.852,136.80,283.76,940
+Romilda,3.162,0.1659,36.772,3.02,319.50,942
+Begonia,3.117,0.2135,70.572,58.12,4.01,943
+Hidalgo,5.731,0.6609,38.,84.94,56.54,944
+Barcelona,2.639,0.1610,25.618,215.92,162.15,945
+Poesia,3.116,0.1433,36.210,137.88,37.67,946
+Monterosa,2.754,0.2472,26.060,131.44,339.25,947
+Hel,3.01,0.1938,63.494,110.97,250.19,949
+Caia,2.992,0.2440,88.692,142.18,356.59,952
+Li,3.132,0.1745,58.771,30.93,150.97,954
+Camelia,2.919,0.0813,91.548,316.28,226.01,957
+Asplinda,3.988,0.1838,45.112,227.62,92.67,958
+Arne,3.176,0.2219,45.176,191.37,333.54,959
+Gunnie,2.692,0.0913,36.571,315.38,285.61,961
+Angelica,3.165,0.2784,60.857,268.10,46.98,965
+Muschi,2.719,0.1305,25.509,295.82,178.01,966
+Alsatia,2.64,0.1629,60.867,93.80,6.48,971
+Cohnia,3.056,0.2359,77.827,303.57,93.50,972
+Aralia,3.21,0.1124,51.609,166.74,87.53,973
+Lioba,2.533,0.1097,25.001,34.74,301.98,974
+Benjamina,3.203,0.1057,83.195,145.67,321.01,976
+Philippa,3.116,0.0256,65.471,103.91,71.56,977
+Aidamina,3.203,0.2314,92.105,69.52,132.57,978
+Ilsewa,3.157,0.1384,35.741,228.65,115.59,979
+Anacostia,2.74,0.2026,74.679,32.74,69.61,980
+Martina,3.095,0.2021,32.545,58.16,297.82,981
+Franklina,3.067,0.2340,33.227,145.52,350.89,982
+Gunila,3.161,0.0914,73.87,314.51,348.49,983
+Gretia,2.804,0.1956,32.449,41.72,55.03,984
+Amelia,3.133,0.2035,48.677,317.64,265.44,986
+Wallia,3.137,0.2370,52.651,316.58,16.25,987
+McDonalda,3.14,0.1597,38.556,345.47,254.76,991
+Swasey,3.033,0.0865,27.585,144.62,347.84,992
+Hilaritas,3.088,0.1396,29.128,97.44,146.65,996
+Bodea,3.116,0.2140,31.761,268.43,72.09,998
+Piazzia,3.168,0.2583,47.78,162.91,280.59,1000
+Gaussia,3.209,0.1221,72.711,31.51,145.70,1001
+Lilofee,3.139,0.1599,33.678,135.17,316.88,1003
+Belopolskya,3.399,0.0889,71.60,245.58,214.83,1004
+Arago,3.167,0.1190,61.132,126.31,60.65,1005
+Lagrangea,3.141,0.3582,35.310,206.24,86.21,1006
+"La Paz",3.092,0.0732,41.061,0.31,15.37,1008
+Marlene,2.93,0.1046,46.876,220.23,279.68,1010
+Tombecka,2.683,0.2092,34.613,94.24,99.63,1013
+Christa,3.207,0.0884,82.350,112.38,286.67,1015
+Jacqueline,2.605,0.0778,40.152,73.52,68.10,1017
+Flammario,2.739,0.2849,100.765,316.02,286.60,1021
+Olympiada,2.806,0.1737,34.297,304.17,124.74,1022
+Thomana,3.169,0.0963,58.27,25.15,195.52,1023
+Hale,2.869,0.2215,43.274,97.55,308.00,1024
+Aesculapia,3.152,0.1288,31.225,78.74,131.91,1027
+Lydina,3.405,0.1053,88.526,206.98,24.11,1028
+Vitja,3.121,0.1227,59.717,290.37,5.44,1030
+Arctica,3.047,0.0589,75.400,213.22,310.03,1031
+Pafuri,3.13,0.1417,65.658,206.90,189.02,1032
+Amata,3.154,0.1897,56.063,198.39,324.89,1035
+Ganymed,2.666,0.5331,37.675,140.65,132.43,1036
+Tuckia,3.982,0.2218,58.3,179.19,305.04,1038
+Sonneberga,2.68,0.0610,33.853,281.71,326.52,1039
+Asta,3.073,0.1449,60.571,136.23,344.14,1041
+Amazone,3.236,0.0878,63.920,129.71,298.53,1042
+Beate,3.094,0.0384,31.986,181.83,157.77,1043
+Edwin,2.985,0.0606,29.084,320.65,48.71,1046
+Feodosia,2.732,0.1800,62.218,24.95,183.61,1048
+Gotho,3.092,0.1372,56.296,225.03,41.03,1049
+Merope,3.213,0.1005,60.439,264.46,153.36,1051
+Forsytia,2.923,0.1342,47.780,118.86,295.72,1054
+Wanda,2.894,0.2472,44.657,183.73,114.76,1057
+Mussorgskia,2.642,0.1877,25.227,178.36,87.93,1059
+Ljuba,3.006,0.0705,58.031,124.42,100.58,1062
+Planckia,3.129,0.1096,35.657,2.03,31.30,1069
+Tunica,3.234,0.0800,39.131,169.95,190.77,1070
+Brita,2.801,0.1105,60.862,34.41,29.17,1071
+Malva,3.17,0.2392,53.675,275.91,25.60,1072
+Gellivara,3.186,0.1876,25.992,164.68,289.69,1073
+Beljawskya,3.15,0.1801,49.189,153.60,22.54,1074
+Helina,3.014,0.1097,26.198,97.86,250.67,1075
+Reseda,3.096,0.1483,37.810,94.76,9.26,1081
+Pirola,3.121,0.1801,42.607,57.51,186.41,1082
+Tamariwa,2.687,0.1326,26.476,120.83,109.34,1084
+Amaryllis,3.185,0.0418,69.281,315.60,129.52,1085
+Nata,3.161,0.0537,66.27,158.08,157.52,1086
+Arabis,3.018,0.0901,37.498,314.60,25.46,1087
+Spiraea,3.416,0.0701,35.178,359.35,12.48,1091
+Lilium,2.899,0.0848,40.276,161.50,314.99,1092
+Freda,3.13,0.2710,116.73,100.80,251.20,1093
+Tulipa,3.024,0.0207,27.875,121.62,342.61,1095
+Reunerta,2.6,0.1941,42.333,81.47,247.65,1096
+Hakone,2.688,0.1161,26.684,11.05,81.18,1098
+Clematis,3.23,0.0788,33.765,64.61,105.71,1101
+Pepita,3.07,0.1108,36.632,200.02,117.54,1102
+Fragaria,3.012,0.1065,38.206,16.13,223.64,1105
+Lictoria,3.184,0.1231,79.079,195.82,350.97,1107
+Demeter,2.428,0.2569,25.285,144.52,78.07,1108
+Tata,3.224,0.0983,61.817,334.23,0.16,1109
+Polonia,3.017,0.1081,39.661,230.01,87.07,1112
+Katja,3.122,0.1367,44.792,269.41,118.78,1113
+Lorraine,3.095,0.0716,75.631,64.22,207.58,1114
+Sabauda,3.099,0.1737,75.907,348.06,56.68,1115
+Catriona,2.929,0.2245,38.741,303.08,83.10,1116
+Hanskya,3.214,0.0436,70.954,218.47,337.04,1118
+Euboea,2.612,0.1551,29.443,204.44,229.93,1119
+China,3.126,0.2176,26.084,140.49,10.39,1125
+Mimi,2.594,0.2651,46.006,138.79,282.70,1127
+Astrid,2.788,0.0445,41.851,226.99,234.40,1128
+Neujmina,3.022,0.0838,34.576,145.18,139.66,1129
+Hollandia,2.687,0.2755,27.235,18.26,270.69,1132
+Colchis,2.666,0.1144,50.592,90.65,3.33,1135
+Mercedes,2.567,0.2537,25.296,194.73,148.73,1136
+Crimea,2.772,0.1103,29.179,45.99,310.07,1140
+Odysseus,5.241,0.0917,114.624,298.57,237.02,1143
+Oda,3.764,0.0834,56.337,350.99,217.29,1144
+Biarmia,3.043,0.2555,32.925,121.59,63.64,1146
+Rarahu,3.019,0.1085,27.512,218.13,175.77,1148
+Volga,2.898,0.0963,52.377,218.19,116.41,1149
+Astronomia,3.393,0.0709,55.715,273.55,205.02,1154
+Arabia,3.181,0.1442,29.113,114.80,312.38,1157
+Granada,2.379,0.0589,28.641,105.66,312.44,1159
+Larissa,3.925,0.1056,40.379,160.28,206.78,1162
+Saga,3.219,0.0425,32.429,147.38,200.73,1163
+Imprinetta,3.127,0.2114,53.187,147.54,96.68,1165
+Sakuntala,2.536,0.2087,26.011,208.11,189.85,1166
+Dubiago,3.416,0.0684,63.12,202.76,72.72,1167
+Rusthawelia,3.175,0.1945,82.229,57.65,292.30,1171
+Aneas,5.225,0.1061,118.020,354.37,50.81,1172
+Anchises,5.283,0.1393,99.549,297.39,41.07,1173
+Gonnessia,3.35,0.0337,91.98,229.98,253.35,1177
+Rita,3.987,0.1555,97,74.62,205.85,1180
+Turnera,3.023,0.1011,34.290,191.01,296.26,1186
+Afra,2.639,0.2233,32.348,189.94,74.90,1187
+Terentia,2.931,0.1119,59.246,57.91,95.41,1189
+Alfaterna,2.896,0.0463,47.397,135.54,56.42,1191
+Aletta,2.916,0.0905,41.358,134.42,244.22,1194
+Sheba,2.652,0.1801,25.274,248.42,262.69,1196
+Rhodesia,2.882,0.2340,47.741,244.72,277.07,1197
+Geldonia,3.017,0.0319,30.395,265.04,291.40,1199
+Imperatrix,3.066,0.1060,42.006,47.99,52.45,1200
+Strenua,2.699,0.0388,35.825,131.94,166.11,1201
+Marina,3.999,0.1676,54.93,183.12,307.54,1202
+Nanna,2.885,0.2500,35.18,137.91,177.23,1203
+Troilus,5.253,0.0925,100.477,304.66,295.44,1208
+Pumma,3.171,0.1276,26.889,222.40,176.84,1209
+Morosovia,3.009,0.0623,33.663,107.34,166.53,1210
+Bressole,2.928,0.1599,45.809,63.44,211.21,1211
+Francette,3.948,0.1898,76.387,123.87,348.16,1212
+Algeria,3.138,0.1284,29.175,125.59,110.42,1213
+Richilde,2.712,0.1171,36.668,200.24,32.73,1214
+Tina,2.793,0.2504,25.781,51.01,59.86,1222
+Geranium,3.217,0.1924,46.269,296.31,303.21,1227
+Tilia,3.225,0.1664,27.795,196.03,166.68,1229
+Cortusa,3.187,0.1372,36.367,92.41,340.96,1232
+Kobresia,2.555,0.0566,33.323,144.39,333.84,1233
+Genevieve,2.613,0.0765,39.81,181.34,307.14,1237
+Centenaria,2.866,0.1760,63.035,326.52,24.04,1240
+Dysona,3.19,0.1006,79.190,206.66,320.59,1241
+Zambesia,2.737,0.1902,47.594,126.64,54.07,1242
+Pamela,3.095,0.0463,69.883,99.33,52.17,1243
+Deira,2.343,0.0982,31.799,55.47,260.87,1244
+Calvinia,2.895,0.0832,29.751,338.95,207.07,1245
+Memoria,3.131,0.1763,38.906,55.58,138.88,1247
+Jugurtha,2.723,0.0161,28.468,256.62,341.78,1248
+Erfordia,3.134,0.0305,51.540,106.73,240.38,1254
+Schilowa,3.143,0.1743,33.669,300.03,133.32,1255
+Normannia,3.896,0.0795,68.245,209.95,101.60,1256
+Sicilia,3.184,0.0444,45.669,222.57,77.41,1258
+Ogyalla,3.102,0.1268,36.111,22.35,150.31,1259
+Legia,3.139,0.1784,32.576,341.84,104.17,1261
+Sniadeckia,3.003,0.0044,71.011,274.57,161.91,1262
+Varsavia,2.665,0.1884,49.29,216.61,287.14,1263
+Letaba,2.866,0.1562,66.040,77.16,31.75,1264
+Tone,3.356,0.0509,75.470,357.35,299.80,1266
+Libya,3.98,0.1028,96.710,357.44,118.59,1268
+Rollandia,3.9,0.0984,104.893,120.91,19.46,1269
+Isergina,3.141,0.1208,47.524,81.50,271.99,1271
+Cimbria,2.681,0.1673,27.622,142.12,197.92,1275
+Ucclia,3.177,0.0909,36.499,299.34,337.97,1276
+Dolores,2.7,0.2372,32.587,310.35,47.31,1277
+Baillauda,3.428,0.0473,50.83,317.70,92.79,1280
+Jeanne,2.557,0.2078,25.716,258.29,72.75,1281
+Utopia,3.124,0.1219,57.702,311.75,77.79,1282
+Komsomolia,3.18,0.2219,29.569,263.20,234.76,1283
+Latvia,2.645,0.1719,41.128,130.17,115.38,1284
+Julietta,2.994,0.0499,42.430,346.34,68.67,1285
+Santa,2.886,0.0657,31.378,4.90,52.94,1288
+Phryne,3.012,0.0958,27.418,330.96,118.73,1291
+Antwerpia,2.687,0.2318,37.199,14.50,312.95,1294
+Deflotte,3.39,0.1240,47.407,25.31,274.88,1295
+Andree,2.417,0.1438,26.298,133.89,236.63,1296
+Nocturna,3.129,0.1450,37.802,76.26,58.77,1298
+Marcelle,2.782,0.0066,28.194,49.38,350.18,1300
+Werra,3.111,0.1752,35.041,179.54,354.17,1302
+Luthera,3.228,0.1035,81.685,109.50,100.77,1303
+Arosa,3.197,0.1206,43.613,123.10,148.09,1304
+Scythia,3.144,0.0964,66.780,62.81,141.56,1306
+Halleria,2.908,0.0107,46.951,131.36,163.82,1308
+Hyperborea,3.206,0.1492,57.570,207.61,244.50,1309
+Vassar,3.097,0.2108,36.28,34.02,261.61,1312
+Bronislawa,3.209,0.0746,64.863,225.06,21.45,1315
+Disa,2.988,0.2054,25.651,346.50,316.29,1319
+Impala,2.991,0.2290,37.331,335.29,206.06,1320
+Majuba,2.938,0.1702,37.137,85.85,345.05,1321
+Tugela,3.237,0.1478,78.295,144.63,137.76,1323
+Losaka,2.667,0.2253,26.336,343.52,278.29,1326
+Devota,3.501,0.1352,53.697,255.12,174.01,1328
+Spiridonia,3.172,0.0746,68.417,23.95,3.79,1330
+Solvejg,3.097,0.1905,36.824,75.57,184.53,1331
+Marconia,3.06,0.1332,46.796,259.90,348.96,1332
+Lundmarka,2.915,0.0932,27.621,243.48,129.30,1334
+Gerarda,2.911,0.0996,40.875,214.83,202.26,1337
+Yvette,3.183,0.1272,29.451,40.67,224.65,1340
+Potomac,3.982,0.1812,72.976,155.73,332.83,1345
+Patria,2.573,0.0669,32.40,295.79,201.18,1347
+Uzbekistania,3.197,0.0684,60.010,49.81,64.18,1351
+Maartje,3.009,0.0962,39.013,77.75,96.96,1353
+Botha,3.127,0.2158,41.732,181.25,250.21,1354
+Nyanza,3.081,0.0513,60.895,239.56,301.99,1356
+Khama,3.186,0.1550,38.321,19.42,282.89,1357
+Prieska,3.119,0.0694,46.096,159.33,342.60,1359
+Tarka,2.633,0.2147,33.316,113.97,287.91,1360
+Leuschneria,3.082,0.1309,29.637,345.37,172.94,1361
+Griqua,3.213,0.3728,26.936,256.17,261.72,1362
+Piccolo,2.876,0.1393,27.55,208.47,282.89,1366
+Ostanina,3.118,0.2110,42.401,288.77,128.09,1369
+Resi,3.206,0.1208,27.155,49.28,103.13,1371
+Haremari,2.765,0.1489,26.491,227.07,88.09,1372
+Kniertje,2.68,0.1806,26.517,288.78,275.70,1384
+Abastumani,3.437,0.0362,95.849,209.04,332.66,1390
+Pierre,2.607,0.2034,26.44,259.22,44.08,1392
+Idelsonia,2.717,0.2951,26.531,8.51,192.29,1403
+Ajax,5.287,0.1142,83.990,359.08,61.41,1404
+Trusanda,3.106,0.0954,35.423,229.05,187.34,1408
+Isko,2.675,0.0572,35.54,251.42,207.42,1409
+Brauna,3.002,0.0580,28.272,229.30,94.31,1411
+Renauxa,3.018,0.1080,27.552,135.21,65.94,1416
+Esperanto,3.089,0.0841,43.31,260.19,162.39,1421
+Sundmania,3.19,0.0566,64.691,110.95,303.49,1424
+Ruvuma,2.751,0.2109,35.406,151.73,241.63,1427
+Mombasa,2.809,0.1416,52.464,280.63,252.48,1428
+Margot,3.021,0.0677,27.178,27.52,147.69,1434
+Salonta,3.148,0.0619,53.769,249.37,31.12,1436
+Diomedes,5.212,0.0450,117.786,352.97,128.68,1437
+Wendeline,3.159,0.2382,37.511,321.32,129.28,1438
+Vogtia,3.995,0.1163,50.561,113.07,101.38,1439
+Pannonia,3.154,0.1377,26.363,226.05,310.50,1444
+Saldanha,3.205,0.2211,37.815,227.14,65.33,1456
+Magnya,3.149,0.2291,29.188,44.18,328.54,1459
+Jean-Jacques,3.126,0.0490,35.145,110.00,334.26,1461
+Zamenhof,3.149,0.1082,27.366,290.17,186.90,1462
+Nordenmarkia,3.152,0.1941,36.547,90.60,79.94,1463
+Mashona,3.387,0.1279,89.160,147.75,350.39,1467
+Linzia,3.125,0.0626,74.780,339.19,206.22,1469
+Carla,3.158,0.0705,36.97,317.67,341.55,1470
+Tornio,2.716,0.1192,28.719,180.25,93.87,1471
+Bonsdorffia,3.207,0.2659,25.851,342.75,105.12,1477
+Tubingia,3.019,0.0420,33.770,222.31,314.60,1481
+Postrema,2.737,0.2059,40.871,181.99,126.97,1484
+Boda,3.133,0.1237,25.671,216.97,107.21,1487
+Attila,3.189,0.1511,26.789,194.83,26.40,1489
+Sigrid,2.43,0.2019,28.905,14.56,1.63,1493
+Lahti,3.104,0.2355,31.605,96.12,96.73,1498
+Arenda,2.731,0.0887,35.518,108.11,273.80,1502
+Oulu,3.96,0.1427,79.872,174.36,237.85,1512
+Henry,2.621,0.1860,26.442,228.65,94.18,1516
+Beograd,2.716,0.0445,39.524,153.61,229.57,1517
+Kajaani,3.125,0.2407,31.166,19.82,338.94,1519
+Imatra,3.111,0.0949,53.435,104.80,119.03,1520
+Joensuu,3.11,0.1214,45.056,17.77,1.31,1524
+Oterma,3.986,0.2014,56.319,248.97,294.69,1529
+Borrelly,3.143,0.1912,26.791,191.26,250.35,1539
+Kevola,2.849,0.0854,43.875,6.61,112.35,1540
+Schalen,3.091,0.1174,42.374,251.36,163.83,1542
+Izsak,3.173,0.1269,26.438,356.59,280.77,1546
+Palomaa,2.786,0.0813,30.761,217.73,87.98,1548
+Wingolfia,3.435,0.1085,28.65,350.31,267.12,1556
+Jarnefelt,3.221,0.0280,54.977,7.61,301.06,1558
+Fricke,3.196,0.1265,25.352,346.65,41.75,1561
+Srbija,3.17,0.1981,41.681,58.37,232.68,1564
+Alikoski,3.211,0.0823,69.242,49.44,110.41,1567
+Evita,3.149,0.1329,36.346,19.37,248.35,1569
+Posnania,3.109,0.2042,31.500,66.07,354.17,1572
+Meyer,3.542,0.0342,57.785,15.91,260.16,1574
+Fabiola,3.144,0.1675,27.357,49.68,246.78,1576
+Kirkwood,3.928,0.2408,47.077,38.26,1.72,1578
+Herrick,3.435,0.1260,46.925,131.91,279.48,1579
+Abanderada,3.159,0.1229,29.508,321.88,89.72,1581
+Martir,3.158,0.1262,37.252,310.90,128.13,1582
+Antilochus,5.14,0.0536,108.842,16.09,186.83,1583
+Union,2.927,0.3092,55.271,259.51,264.32,1585
+Tanga,2.644,0.1116,26.572,82.96,189.72,1595
+Itzigsohn,2.89,0.1304,45.534,264.72,160.11,1596
+Giomus,3.133,0.1429,41.295,296.18,355.53,1599
+Neva,2.756,0.0956,39.564,305.98,256.30,1603
+Tombaugh,3.021,0.1030,32.33,299.45,38.20,1604
+Milankovitch,3.02,0.0739,29.598,252.90,275.55,1605
+Brenda,2.583,0.2491,29.64,328.57,229.25,1609
+Goldschmidt,3.001,0.0693,48.007,210.26,346.66,1614
+Bardwell,3.119,0.1829,29.139,94.83,254.07,1615
+Vivian,3.141,0.1541,27.851,350.46,320.78,1623
+Rabe,3.199,0.0917,26.270,197.54,26.28,1624
+"The NORC",3.195,0.2308,53.317,64.01,286.65,1625
+Strobel,3.011,0.0664,59.345,186.88,288.43,1628
+Siebohme,2.654,0.1372,29.351,73.89,126.61,1632
+Chimay,3.206,0.1239,37.428,150.39,68.37,1633
+Swings,3.073,0.0459,52.994,54.55,238.16,1637
+Bower,2.573,0.1479,35.676,328.86,106.52,1639
+Tana,3.021,0.0984,25.66,160.36,0.50,1641
+Waterfield,3.062,0.1100,28.146,150.03,106.45,1645
+Menelaus,5.211,0.0215,42.716,222.33,294.01,1647
+Heckmann,2.435,0.1632,30.202,172.68,56.81,1650
+Bojeva,3.017,0.0866,25.115,100.57,332.97,1654
+"Comas Sola",2.785,0.2315,35.943,303.72,323.45,1655
+Punkaharju,2.783,0.2601,28.010,222.92,36.43,1659
+Dagmar,3.139,0.1093,42.377,49.73,178.41,1669
+Gezelle,3.172,0.2777,26.205,103.21,254.99,1672
+Groeneveld,3.191,0.1265,32.386,322.26,4.29,1674
+Hveen,3.156,0.1100,42.665,143.17,120.94,1678
+Nevanlinna,3.116,0.1532,52.686,163.56,89.80,1679
+Iguassu,3.098,0.1260,30.210,42.04,154.94,1684
+"De Sitter",3.165,0.1596,29.661,178.36,294.62,1686
+Glarona,3.165,0.1686,37.850,342.53,316.89,1687
+Mayrhofer,3.042,0.0977,33.810,323.63,154.94,1690
+Oort,3.162,0.1762,33.644,160.80,232.47,1691
+Subbotina,2.787,0.1373,36.075,141.81,111.76,1692
+Hertzsprung,2.797,0.2733,37.772,141.66,234.81,1693
+Christophe,3.162,0.1075,26.234,220.47,132.60,1698
+Kalahari,2.856,0.1434,34.645,35.43,241.31,1702
+Polit,2.91,0.3079,28.706,171.11,248.74,1708
+Angola,3.164,0.1543,66.892,110.76,17.87,1712
+Peter,2.738,0.0902,26.656,132.60,317.14,1716
+Wells,3.148,0.0494,43.576,23.81,137.90,1721
+Klemola,3.014,0.0405,33.449,151.91,2.15,1723
+Vladimir,2.711,0.0580,38.476,114.14,297.37,1724
+Hoffmeister,2.789,0.0439,25.250,20.43,69.55,1726
+Smuts,3.168,0.1285,54.784,321.59,203.14,1731
+Zhongolovich,2.778,0.2293,26.425,64.32,186.28,1734
+ITA,3.137,0.1304,61.865,123.04,275.10,1735
+Brouwer,3.954,0.2089,62.524,132.65,47.73,1746
+Mauderli,3.948,0.2165,44.908,66.07,198.53,1748
+Telamon,5.144,0.1091,64.898,307.78,113.36,1749
+Cunningham,3.942,0.1695,79.52,282.60,110.09,1754
+Sandra,3.148,0.1278,34.765,289.54,332.16,1760
+Cogshall,3.092,0.1199,26.970,14.15,80.23,1764
+Wrubel,3.175,0.1779,38.299,232.84,265.55,1765
+Makover,3.128,0.1696,46.886,344.52,316.43,1771
+Kuiper,3.102,0.0171,39.952,319.55,312.19,1776
+Kippes,3.017,0.0569,28.164,90.30,338.80,1780
+Raahe,3.021,0.1115,25.532,353.32,347.07,1786
+Patsayev,2.748,0.1419,29.394,34.71,74.93,1791
+Finsen,3.134,0.1532,38.050,140.30,342.10,1794
+Riga,3.354,0.0556,68.167,37.69,26.43,1796
+Dirikis,3.15,0.1092,28.098,156.65,88.44,1805
+Bruwer,3.138,0.1100,28.072,51.01,136.44,1811
+Beethoven,3.153,0.1920,30.598,22.82,358.40,1815
+Laputa,3.134,0.2289,54.165,75.52,166.00,1819
+Kashirina,3.063,0.1073,27.016,70.14,222.96,1828
+Mrkos,3.216,0.0989,29.351,0.97,80.70,1832
+Ursa,3.215,0.0142,40.054,207.51,47.72,1838
+Masaryk,3.415,0.1103,40.240,198.37,124.21,1841
+Jarmila,2.654,0.1702,28.965,25.85,32.50,1843
+Susilva,3.016,0.0510,26.800,13.20,72.28,1844
+Kovalevskaya,3.212,0.0979,44.634,312.61,245.20,1859
+Deiphobus,5.133,0.0461,118.220,5.24,359.95,1867
+Thersites,5.311,0.1103,68.163,29.25,170.96,1868
+Glaukos,5.243,0.0338,47.649,330.00,130.92,1870
+Astyanax,5.232,0.0350,27.828,298.84,165.57,1871
+Helenos,5.322,0.0495,34.046,340.78,115.13,1872
+Agenor,5.228,0.0916,50.799,75.12,358.08,1873
+Marsden,3.945,0.2055,35.642,86.87,305.93,1877
+Pakhmutova,3.087,0.1154,35.243,324.35,83.95,1889
+Konoshenkova,3.209,0.1385,25.68,189.75,15.80,1890
+Moravia,3.245,0.0733,28.096,81.32,148.97,1901
+Shaposhnikov,3.976,0.2220,83.430,26.76,266.97,1902
+Adzhimushkaj,3,0.0480,27.642,292.74,356.64,1903
+Mikhailov,3.046,0.0527,37.201,329.86,326.99,1910
+Schubart,3.973,0.1720,67.476,336.46,181.47,1911
+Lucifer,2.898,0.1417,34.437,293.67,341.88,1930
+Lugano,2.674,0.1383,33.905,291.61,255.22,1936
+Loretta,3.125,0.1246,30.365,310.48,189.49,1939
+Whipple,3.06,0.0607,37.481,307.67,184.85,1940
+Iso-Heikkila,3.156,0.0414,31.611,119.22,145.10,1947
+Hesburgh,3.109,0.1439,37.501,103.28,339.53,1952
+Chandra,3.106,0.1651,34.278,162.14,318.83,1958
+Guisan,2.525,0.1229,27.004,107.27,263.66,1960
+Dufour,3.193,0.1249,50.31,103.97,56.49,1961
+Bezovec,2.422,0.2104,35.536,204.40,355.46,1963
+Colocolo,3.185,0.0774,26.269,125.95,164.51,1973
+Fedynskij,3.011,0.0874,36.413,141.59,127.02,1984
+Hopmann,3.118,0.1563,35.51,261.12,233.55,1985
+Shane,2.679,0.2070,25.15,297.97,89.90,1994
+Hirayama,3.113,0.1178,38.277,327.40,356.17,1999
+McCuskey,2.386,0.1145,25.733,115.23,185.76,2007
+Konstitutsiya,3.217,0.0965,52.023,309.09,201.76,2008
+Voloshina,3.117,0.1406,26.558,188.40,6.01,2009
+Nortia,3.169,0.1148,42.769,51.63,310.17,2025
+Ethel,3.071,0.1263,36.007,202.14,296.69,2032
+Chalonge,3.111,0.1903,33.901,294.73,90.86,2040
+Ortutay,3.105,0.1126,48.460,211.06,60.16,2043
+Tamriko,3.012,0.0827,26.799,284.24,203.34,2052
+Chiron,13.71,0.3766,166,184.80,339.62,2060
+Aksnes,3.97,0.1828,46.003,31.35,297.02,2067
+Dangreen,2.772,0.0978,34.322,66.93,321.42,2068
+Hubble,3.154,0.1894,38.471,3.97,69.70,2069
+Galle,3.138,0.2523,26.330,121.67,29.31,2097
+Toronto,3.186,0.1217,35.874,278.05,290.43,2104
+"Otto Schmidt",2.436,0.0044,28.999,85.49,75.58,2108
+Tyumenia,3.058,0.1279,51.485,97.99,74.64,2120
+Tanya,3.212,0.0319,37.736,254.68,187.96,2127
+Zhukov,2.781,0.0797,30.787,321.31,337.26,2132
+Priscilla,3.193,0.0474,34.957,259.39,140.89,2137
+Kemerovo,2.988,0.0585,34.539,281.98,117.96,2140
+Blaauw,3.212,0.1014,40.549,228.41,278.06,2145
+Stentor,5.19,0.1022,50.755,354.18,274.25,2146
+Epeios,5.217,0.0584,37.980,358.91,232.24,2148
+Hannibal,3.125,0.2207,44.559,280.66,141.88,2152
+Young,3.125,0.1768,27.115,226.34,23.93,2165
+Maresjev,3.14,0.1152,28.324,200.78,166.79,2173
+Fujian,3.178,0.0938,35.690,52.70,121.70,2184
+Pyatigoriya,3.138,0.0797,29.217,225.98,147.16,2192
+Jackson,3.103,0.0751,58.265,152.88,224.08,2193
+Ellicott,3.436,0.0568,57.384,302.99,305.07,2196
+Lyyli,2.59,0.4048,25.16,7.66,284.15,2204
+Antenor,5.165,0.0129,97.658,188.88,307.61,2207
+Pushkin,3.494,0.0308,40.850,192.53,3.34,2208
+Carol,3.154,0.2687,25.860,328.42,137.58,2214
+Eltigen,3.157,0.1699,28.800,23.51,173.50,2217
+Wotho,3.045,0.1568,28.158,357.24,324.31,2218
+Mannucci,3.152,0.1140,38.814,41.47,293.82,2219
+Lermontov,3.122,0.1620,29.644,344.59,340.43,2222
+Sarpedon,5.253,0.0190,77.480,20.89,52.82,2223
+Soyuz-Apollo,3.141,0.1818,26.080,266.33,285.11,2228
+Vittore,3.207,0.2156,41.688,15.56,274.28,2235
+Paracelsus,3.195,0.1061,33.978,187.12,2.98,2239
+Alcathous,5.178,0.0664,113.682,69.94,293.05,2241
+Hekatostos,2.637,0.1336,29.28,283.73,316.50,2245
+Bowell,3.95,0.0922,48.424,84.58,21.95,2246
+Kanda,3.099,0.1149,26.361,99.20,146.22,2248
+Yamamoto,3.19,0.0804,33.606,320.91,112.95,2249
+Tikhov,2.712,0.1492,29.488,339.52,182.97,2251
+Viipuri,2.693,0.0808,26.255,126.28,173.76,2258
+Neoptolemus,5.198,0.0451,76.435,358.59,321.35,2260
+Shaanxi,3.019,0.1085,26.702,120.89,316.24,2263
+Sabrina,3.127,0.1788,34.192,5.19,79.10,2264
+Tchaikovsky,3.397,0.1817,46.94,190.30,205.34,2266
+Efremiana,3.129,0.0828,29.604,211.04,34.47,2269
+Yazhi,3.156,0.1402,25.790,69.57,189.26,2270
+Kiso,2.762,0.0609,31.229,19.44,179.04,2271
+Kevo,3.041,0.0650,41.429,162.04,295.75,2291
+Daghestan,3.167,0.1258,26.579,6.23,93.33,2297
+Garuda,3.045,0.0545,40.139,32.21,341.34,2307
+Olshaniya,3.143,0.1617,26.395,108.88,330.55,2310
+"El Leoncito",3.645,0.0437,53.14,338.79,185.47,2311
+Duboshin,3.966,0.1584,50.122,65.04,342.22,2312
+Czechoslovakia,3.011,0.1079,25.258,123.32,14.10,2315
+Blarney,3.166,0.1333,35.739,181.87,261.03,2320
+Janice,3.082,0.1805,28.463,141.22,305.04,2324
+Tololo,2.859,0.1592,42.550,179.83,259.44,2326
+Ontake,3.182,0.0348,33.061,215.17,130.96,2330
+Kalm,3.072,0.0608,31.734,324.80,244.33,2332
+Fucik,3.023,0.0740,25.155,265.60,134.70,2345
+Vinata,3.087,0.2140,25.398,229.80,108.16,2347
+Kurchatov,3.109,0.1100,30.069,206.87,119.01,2352
+Hirons,3.236,0.0394,43.072,320.83,355.68,2356
+Phereclos,5.221,0.0474,94.625,34.13,76.06,2357
+Cebriones,5.224,0.0392,95.976,35.84,54.49,2363
+Vladvysotskij,3.084,0.2147,26.090,249.05,16.59,2374
+Radek,3.18,0.2094,32.744,25.68,101.71,2375
+Martynov,3.201,0.1186,41.583,241.86,300.96,2376
+Pannekoek,2.89,0.1394,40.373,305.63,266.66,2378
+Heiskanen,3.164,0.2764,33.157,56.09,176.51,2379
+Suzuki,3.227,0.1926,48.406,217.64,114.17,2393
+Astapovich,2.637,0.2416,31.285,97.68,103.22,2408
+Vibeke,3.195,0.1299,31.782,235.53,46.67,2414
+Nininger,3.237,0.0432,39.505,131.90,283.15,2421
+Simonov,2.914,0.1138,25.654,65.01,5.42,2426
+Tomeileen,3.005,0.0571,31.878,42.97,68.28,2443
+Lederle,2.727,0.1320,29.925,230.27,141.86,2444
+Sholokhov,2.792,0.1167,38.519,328.89,72.38,2448
+Palamedes,5.13,0.0753,65.916,344.76,95.34,2456
+Clavel,3.18,0.1683,25.943,252.26,231.96,2461
+Guinevere,3.966,0.2770,35.688,204.70,183.10,2483
+Kutuzov,3.19,0.1412,27.792,314.89,269.12,2492
+Inge,3.16,0.0625,46.628,2.22,95.56,2494
+Novorossijsk,3.106,0.0928,29.946,127.96,315.08,2520
+Budovicium,3.117,0.1573,32.677,158.20,19.86,2524
+O'Steen,3.151,0.1775,29.877,99.59,286.68,2525
+Houzeau,3.15,0.1670,31.052,84.09,201.52,2534
+Madeline,2.626,0.1631,26.004,198.07,314.30,2569
+Yesenin,3.091,0.1272,27.887,275.99,6.17,2576
+Harimaya-Bashi,3.2,0.0640,28.87,124.21,233.82,2582
+Acamas,5.058,0.0860,25.874,2.50,280.24,2594
+Kathryn,2.894,0.1641,25.144,273.28,1.12,2612
+Plzen,3.045,0.0420,28.007,244.31,195.62,2613
+Jiangxi,3.154,0.2377,49.084,78.73,350.11,2617
+Goto,3.084,0.1757,44.723,345.52,271.76,2621
+Hermod,3.072,0.1268,25.165,223.99,23.93,2630
+Guizhou,3.039,0.1104,32.364,345.10,311.98,2632
+"James Bradley",3.458,0.0489,33.726,107.75,332.63,2634
+Millis,3.137,0.1004,27.878,228.30,333.57,2659
+Gramme,3.177,0.2258,30.364,122.57,208.05,2666
+Pandarus,5.194,0.0700,74.267,66.30,41.89,2674
+Magion,2.45,0.1149,25.418,34.92,283.77,2696
+Albina,3.558,0.0794,51.54,250.47,130.90,2697
+Ueferji,3.195,0.1173,25.838,324.76,344.43,2707
+Handley,3.118,0.1555,25.309,298.39,265.90,2718
+"David Bender",3.034,0.1523,36.974,43.22,28.44,2725
+Cucula,3.188,0.1891,44.841,316.09,133.36,2731
+Hasek,3.16,0.0159,25.409,77.22,141.17,2734
+"Cesky Krumlov",3.096,0.1287,29.804,113.77,300.91,2747
+Idomeneus,5.193,0.0648,53.676,235.12,8.18,2759
+Kacha,3.991,0.1193,57.90,307.00,150.48,2760
+Tenojoki,3.192,0.1383,35.697,319.47,107.02,2774
+Valdaj,3.169,0.0293,27.103,122.99,190.74,2793
+Teucer,5.109,0.0883,89.430,294.59,48.11,2797
+Zappala,3.136,0.1539,32.040,25.28,247.37,2813
+Pien,2.726,0.1889,28.256,263.63,264.93,2816
+Ahti,3.222,0.0491,39.975,278.79,146.89,2826
+Bobhope,3.091,0.1873,41.361,202.51,339.63,2829
+Ylppo,3.221,0.0727,27.994,225.45,71.92,2846
+ASP,3.207,0.1905,25.793,351.32,51.07,2848
+McGetchin,3.355,0.1382,35.066,166.48,251.30,2891
+Filipenko,3.172,0.2030,69.492,13.87,94.23,2892
+Peiroos,5.143,0.0774,86.884,351.25,172.85,2893
+Memnon,5.244,0.0488,56.706,237.79,274.98,2895
+Caltech,3.167,0.1039,58.678,62.92,296.94,2906
+Shimoyama,2.978,0.1550,29.663,306.35,153.60,2908
+Automedon,5.112,0.0278,88.574,341.30,197.09,2920
+Kempchinsky,3.633,0.1052,29.283,358.23,195.23,2932
+Perepadin,3.129,0.1179,46.653,242.49,121.85,2951
+Scholl,3.956,0.2722,32.783,281.46,284.75,2959
+Vladisvyat,3.196,0.1356,32.879,258.96,359.57,2967
+Lautaro,3.34,0.1457,46.184,74.70,188.05,2976
+Poltava,2.848,0.0578,30.690,146.95,86.74,2983
+Hainan,3.415,0.1309,37.189,152.54,341.65,3024
+Higson,3.201,0.0857,45.830,272.02,113.15,3025
+Zhangguoxi,3.019,0.0311,25.58,296.28,4.57,3028
+Krat,3.208,0.1007,43.101,256.58,320.01,3036
+Alku,2.674,0.1859,29.876,328.93,330.95,3037
+Alois,3.132,0.1075,27.493,45.49,330.52,3045
+Strugatskia,3.094,0.2098,26.921,70.14,186.95,3054
+Makhaon,5.218,0.0587,111.655,285.72,203.91,3063
+Horrocks,3.147,0.1046,28.284,284.76,140.47,3078
+Oujianquan,2.929,0.1862,35.887,172.42,184.11,3089
+Herodotus,3.537,0.1145,30.346,58.61,9.24,3092
+Omarkhayyam,3.494,0.0797,30.178,75.55,116.73,3095
+Morabito,3.142,0.2395,26.209,180.20,290.30,3106
+Claytonsmith,3.035,0.0568,36.569,69.53,259.17,3118
+Landgraf,3.144,0.1283,35.886,220.18,266.10,3132
+Kostinsky,3.984,0.2194,50.389,246.41,163.05,3134
+Shantou,3.195,0.0217,36.648,120.66,117.06,3139
+Buchar,3.42,0.0689,36.05,226.88,155.30,3141
+Tosa,3.202,0.1170,33.479,200.28,271.91,3150
+Jones,2.625,0.0896,30.952,17.51,289.99,3152
+Ellington,2.855,0.1970,30.794,132.59,119.06,3156
+Novikov,3.148,0.1478,29.876,233.17,322.37,3157
+Nostalgia,3.154,0.1562,28.690,141.79,315.37,3162
+Wangshouguan,3.181,0.1460,38.766,127.59,25.39,3171
+Paolicchi,2.875,0.0324,41.327,135.53,24.01,3176
+Graff,3.928,0.1138,35.910,137.95,268.18,3202
+Liller,3.094,0.0657,34.919,52.58,129.73,3222
+Victorplatt,3.012,0.0668,27.751,168.93,337.46,3237
+Laocoon,5.225,0.1284,51.695,319.32,16.01,3240
+Farinella,3.205,0.1518,36.553,218.00,317.16,3248
+Bus,3.97,0.1553,31.104,25.00,302.78,3254
+Brownlee,3.165,0.1224,25.579,61.05,314.61,3259
+Drukar,3.407,0.0237,27.397,240.60,226.04,3273
+Behounek,3.226,0.0132,31.455,164.00,98.93,3278
+Paris,5.223,0.1284,118.790,0.93,150.42,3317
+TARDIS,3.184,0.0181,28.238,324.16,85.26,3325
+Gantrisch,3.156,0.2011,34.877,217.03,306.37,3330
+Schaber,3.135,0.2210,26.538,221.67,66.48,3333
+Treshnikov,3.18,0.1329,33.541,251.56,147.73,3339
+Gerla,3.187,0.0467,34.628,128.91,21.67,3346
+Duncombe,3.385,0.0903,33.331,305.53,351.00,3368
+Sinon,5.298,0.0839,37.862,313.35,103.63,3391
+Muazzez,3.392,0.1792,32.519,50.60,315.53,3396
+Danby,3.966,0.2484,36.582,286.35,136.29,3415
+Guth,3.21,0.0649,34.589,330.73,226.21,3419
+Nakano,3.093,0.0484,44.339,297.99,45.25,3431
+Inarradas,3.046,0.2031,25.252,317.99,349.81,3438
+Yashin,3.146,0.1412,25.708,256.78,297.84,3442
+Mentor,5.158,0.0726,126.288,356.15,130.27,3451
+Amelin,3.19,0.0511,29.257,143.39,158.78,3471
+Fichte,3.173,0.1265,29.558,163.90,230.63,3475
+Dongguan,3.159,0.1949,31.53,224.32,25.37,3476
+Colchagua,3.221,0.1195,26.312,66.32,108.02,3495
+Protesilaos,5.282,0.1168,70.225,269.16,115.88,3540
+Eurybates,5.202,0.0903,63.885,354.54,27.20,3548
+Link,2.925,0.1586,26.515,345.25,29.84,3550
+Devine,3.959,0.1296,32.74,260.85,176.77,3561
+Talthybius,5.202,0.0383,73.730,168.37,203.19,3564
+Ojima,3.204,0.1236,28.129,37.70,346.42,3565
+Milanstefanik,3.936,0.1122,34.898,317.93,21.46,3571
+Putilin,3.94,0.1959,49.135,161.05,179.37,3577
+Carestia,3.216,0.2044,42.882,134.09,48.14,3578
+Aisha,3.086,0.1021,27.696,111.36,108.92,3584
+Meriones,5.178,0.0745,87.380,358.24,66.14,3596
+Tumilty,2.981,0.1308,47.829,117.94,311.25,3614
+Safronov,3.162,0.1327,25.209,102.06,111.74,3615
+Sigyn,3.093,0.0782,38.505,335.04,159.32,3631
+"Williams Bay",2.994,0.1272,29.710,145.62,293.51,3641
+Frieden,2.791,0.0793,31.899,180.69,15.58,3642
+Dermott,2.801,0.1033,26.754,13.31,218.41,3647
+Kunming,3.117,0.2423,26.645,333.92,285.26,3650
+Eupraksia,4.02,0.2020,36.657,139.86,39.58,3655
+Lazarev,3.223,0.0811,25.830,314.65,215.53,3660
+Dzus,2.727,0.1999,30.932,74.86,113.44,3687
+Barringer,3.147,0.2020,27.494,29.15,184.02,3693
+Sharon,3.93,0.2057,46.032,271.68,80.25,3694
+Socus,5.212,0.1594,75.661,292.60,57.70,3708
+Polypoites,5.23,0.0626,65.297,317.56,247.45,3709
+Maxhell,3.319,0.1508,27.691,236.93,162.41,3727
+Hurban,2.726,0.1621,26.996,251.33,42.72,3730
+Hancock,3.234,0.1141,53.112,160.39,255.05,3731
+Belinskij,3.185,0.1239,26.73,285.88,105.48,3747
+Kathleen,3.159,0.1069,53.699,43.57,55.22,3754
+Piironen,2.718,0.1180,32.15,178.04,165.75,3759
+Romanskaya,3.125,0.2814,32.882,164.51,83.70,3761
+Monroe,3.095,0.2148,26.601,168.61,224.07,3768
+Chopin,3.132,0.1638,29.346,241.08,192.87,3784
+Leonteus,5.221,0.0901,112.046,311.49,262.24,3793
+Sthenelos,5.205,0.1472,34.531,29.46,36.14,3794
+Thrasymedes,5.325,0.0241,34.285,342.38,205.85,3801
+Tuchkova,3.048,0.0503,38.019,82.47,275.09,3803
+Karma,2.577,0.1310,30.344,163.47,68.61,3811
+Lidaksum,3.175,0.1185,33.611,355.13,35.75,3812
+OISCA,3.984,0.1443,30.769,215.72,23.61,3843
+Neyachenko,3.429,0.1563,25.817,200.35,260.36,3845
+Yoritomo,3.224,0.0653,28.402,296.75,354.85,3902
+Chao,2.933,0.0701,46.247,228.40,208.65,3906
+Radzievskij,3.962,0.2205,29.870,227.19,283.00,3923
+Tret'yakov,3.158,0.1950,51.289,323.18,206.59,3925
+Huruhata,3.108,0.1022,30.644,113.17,251.37,3939
+Shekhtelia,3.256,0.0470,29.305,236.15,13.59,3967
+Voronikhin,2.851,0.1849,31.996,343.47,82.91,3971
+Lise,2.757,0.0708,29.049,74.37,102.10,3976
+Klepesta,2.886,0.0024,29.223,238.85,223.86,3978
+Heimdal,3.945,0.2420,35.675,111.94,197.89,3990
+Schumann,3.429,0.0943,36.115,230.92,117.33,4003
+Euryalos,5.182,0.0570,45.515,331.74,77.04,4007
+Heizman,3.419,0.0325,36.83,249.89,106.37,4014
+Thestor,5.281,0.0577,68.733,326.36,198.34,4035
+Miyamotoyohko,3.017,0.0553,26.244,84.24,159.94,4041
+Lowengrub,3.231,0.1004,31.322,196.50,245.19,4045
+Demophon,5.249,0.1205,45.683,311.39,59.91,4057
+Deipylos,5.242,0.1559,84.043,281.80,307.52,4060
+Euforbo,5.187,0.1194,95.619,341.58,318.50,4063
+Menestheus,5.143,0.0743,67.625,261.48,316.38,4068
+Rostovdon,3.204,0.1578,25.982,355.16,126.36,4071
+Podalirius,5.268,0.1222,85.495,9.04,356.70,4086
+Hrabal,3.119,0.0388,45.507,125.14,177.76,4112
+Stasik,3.167,0.1048,29.130,129.67,100.26,4131
+Kalchas,5.17,0.0447,46.462,39.65,165.64,4138
+Branham,3.004,0.1208,33.748,267.75,220.06,4140
+Vladvasil'ev,3.156,0.0332,32.494,46.03,228.55,4144
+Celsius,3.398,0.1625,37.303,30.79,32.14,4169
+Tamashima,3.107,0.0679,29.910,151.40,275.43,4186
+Shuya,3.895,0.0273,36.714,3.57,222.89,4196
+Orosz,3.161,0.2272,32.985,247.55,13.64,4201
+Kiselev,3.205,0.0718,30.413,44.85,218.47,4208
+Briggs,3.157,0.0818,31.303,116.11,13.42,4209
+Susa,2.918,0.1867,34.730,145.60,181.85,4224
+Damiaan,2.865,0.2560,33.065,238.61,133.00,4226
+"van den Bergh",3.945,0.1338,28.461,242.76,19.90,4230
+Lidov,3.439,0.0391,32.880,297.31,145.50,4236
+Garibaldi,3.989,0.1603,38.606,119.76,94.72,4317
+Bata,3.22,0.1034,25.790,124.79,96.44,4318
+Poulydamas,5.237,0.0980,82.032,257.80,159.67,4348
+Tiburcio,2.618,0.2425,28.091,242.35,281.32,4349
+Ortizmoreno,3.245,0.0587,30.74,276.47,34.64,4436
+Sykes,3.163,0.2537,26.693,322.24,291.95,4438
+Carolyn,3.989,0.2815,28.645,249.22,117.26,4446
+Sobinov,3.138,0.0963,30.02,170.33,309.69,4449
+Bihoro,2.92,0.1843,38.742,290.40,30.91,4460
+Dracius,5.199,0.0619,76.595,289.97,7.86,4489
+Eurypylos,5.218,0.0539,45.524,357.86,179.62,4501
+Phoinix,5.135,0.0973,63.836,19.55,84.80,4543
+Massachusetts,2.613,0.0682,33.036,0.53,37.27,4547
+Fanynka,3.187,0.1184,26.315,198.28,4.46,4554
+Pizarro,3.11,0.1055,29.012,276.44,119.79,4609
+Zadunaisky,3.211,0.0706,32.685,345.79,270.95,4617
+Falta,3.212,0.0620,28.824,171.59,12.29,4663
+Takuboku,3.188,0.0480,28.115,286.65,177.02,4672
+Khryses,5.196,0.1219,37.766,273.98,66.23,4707
+Polydoros,5.247,0.0607,54.964,239.49,103.04,4708
+Ennomos,5.266,0.0228,91.433,328.95,76.74,4709
+Iwaizumi,3.146,0.1374,28.778,295.79,350.42,4712
+Medesicaste,5.111,0.0502,62.097,301.64,344.18,4715
+Agelaos,5.204,0.1120,50.378,258.27,315.17,4722
+Froeschle,3.159,0.0725,29.981,300.88,143.71,4732
+Panthoos,5.27,0.0098,53.025,327.32,175.13,4754
+Hartley,3.171,0.2384,34.349,308.08,26.54,4768
+Frankdrake,3.162,0.0693,27.570,270.20,184.81,4772
+Iphidamas,5.159,0.0454,49.528,211.85,163.84,4791
+Lykaon,5.253,0.0924,50.870,289.15,283.61,4792
+Asteropaios,5.201,0.0916,57.647,261.76,90.02,4805
+Dares,5.131,0.0433,42.770,240.72,168.21,4827
+Misenus,5.164,0.0411,45.954,153.26,129.59,4828
+Sergestus,5.178,0.0495,32.220,321.40,118.99,4829
+Palinurus,5.263,0.1414,52.058,299.36,209.67,4832
+Meges,5.231,0.0930,80.165,8.95,281.26,4833
+Thoas,5.207,0.1378,72.331,325.57,352.58,4834
+Asaeus,5.197,0.2520,30.175,292.94,355.22,4835
+Medon,5.214,0.1086,63.277,302.21,33.91,4836
+Bickerton,3.197,0.1379,28.328,179.12,45.47,4837
+Megantic,3.091,0.1176,26.690,68.78,222.89,4843
+Gubbio,2.632,0.1454,25.733,226.89,15.73,4860
+Polites,5.17,0.0193,57.251,35.26,280.60,4867
+Tomoegozen,3.106,0.1705,28.787,197.03,98.47,4896
+Thessandrus,5.203,0.0438,51.263,320.45,270.91,4902
+Rephiltim,3.123,0.0517,35.676,8.18,358.40,4930
+Texstapa,3.113,0.0159,25.603,61.12,291.35,4932
+Askalaphus,5.321,0.0490,48.209,132.05,206.38,4946
+Niinoama,3.149,0.0104,35.842,54.89,317.53,4959
+Glia,3.151,0.0380,30.022,135.20,229.31,4967
+Showa,3.43,0.0766,27.958,59.45,130.34,4973
+Eurymedon,5.264,0.0865,36.960,29.24,335.12,5012
+Roccapalumba,3.15,0.0850,32.547,194.25,68.26,5022
+Agapenor,5.164,0.0529,27.850,358.85,87.31,5023
+Bechmann,3.226,0.0550,26.630,359.45,120.66,5024
+Mecisteus,5.193,0.0763,39.843,337.31,74.16,5025
+Androgeos,5.302,0.0668,59.786,332.49,345.17,5027
+Halaesus,5.26,0.1315,50.770,346.54,11.90,5028
+Theotes,5.195,0.0352,41.899,291.80,103.89,5041
+Arai,3.108,0.0647,28.47,125.23,188.82,5070
+Imbrius,5.199,0.1099,49.251,311.39,16.79,5119
+Bitias,5.267,0.1122,47.987,311.89,24.11,5120
+Cynus,5.228,0.1031,35.387,288.74,32.22,5123
+Achaemenides,5.245,0.0260,51.922,297.99,350.49,5126
+Ilioneus,5.198,0.0121,60.711,270.11,105.70,5130
+Achates,5.186,0.2732,80.958,331.74,331.79,5144
+Pholus,20.33,0.5705,190,119.58,354.71,5145
+Gierasch,2.657,0.1739,27.494,21.97,39.77,5153
+Yabuki,3.189,0.0877,31.503,255.00,300.63,5192
+Oloosson,5.203,0.0513,48.197,5.79,104.51,5209
+Nastes,5.149,0.0449,29.035,93.69,47.10,5233
+Amphilochos,5.18,0.0289,36.689,72.69,128.38,5244
+Ulysses,5.226,0.1228,76.147,336.35,344.09,5254
+Rhoeo,5.166,0.0781,53.275,273.94,230.09,5258
+Epeigeus,5.21,0.0722,44.741,142.19,201.31,5259
+Brucegoldberg,3.081,0.1699,33.25,208.81,93.41,5262
+Arrius,3.201,0.0144,25.615,136.25,320.76,5263
+Telephus,5.209,0.1120,68.472,284.00,359.15,5264
+Pyrrhus,5.196,0.1505,48.356,335.79,356.78,5283
+Orsilocus,5.226,0.0845,50.159,319.45,343.25,5284
+Krethon,5.186,0.0509,49.606,30.39,257.04,5285
+Filatov,3.158,0.0234,45.693,287.68,252.76,5316
+Missing,3.112,0.1461,25.260,193.06,64.05,5336
+Aoki,3.2,0.0971,30.782,128.05,3.12,5337
+Rozhdestvenskij,3.238,0.0141,28.062,349.64,21.46,5360
+Vitagliano,3.966,0.0816,34.807,129.90,338.45,5368
+Hokutosei,3.169,0.1011,38.657,230.73,249.98,5374
+Kameoka,3.155,0.1267,26.301,276.49,3.36,5435
+Eumelos,5.203,0.0781,37.696,291.16,220.73,5436
+Lorre,2.748,0.2758,28.072,113.69,238.65,5438
+Mulius,5.112,0.0749,35.096,354.67,95.66,5476
+Rumyantsev,3.413,0.0481,25.518,340.34,278.18,5495
+Cloanthus,5.247,0.1182,39.773,355.34,121.59,5511
+Durisen,2.94,0.2196,36.475,120.03,308.07,5567
+Jimmiller,3.165,0.0510,25.856,223.01,111.21,5594
+Rausudake,3.982,0.0526,45.677,235.71,9.10,5603
+Gyas,5.168,0.1196,28.168,329.82,331.13,5637
+Deikoon,5.238,0.1068,41.455,14.31,92.87,5638
+Axius,5.144,0.1669,59.295,296.14,269.02,5648
+Traversa,3.142,0.1584,26.88,313.77,228.87,5651
+Amphimachus,5.212,0.0772,53.921,18.15,108.82,5652
+Hildebrand,3.964,0.2355,34.37,245.15,1.82,5661
+Rosstaylor,3.177,0.1107,29.619,78.81,197.61,5670
+Eneev,3.943,0.1647,38.81,242.69,296.01,5711
+Somerville,3.14,0.2164,28.306,57.03,103.15,5771
+Peterson,3.493,0.0326,27.077,142.03,110.98,5833
+Bhanji,3.178,0.0081,28.39,200.97,109.93,5849
+Mickiewicz,3.046,0.1569,26.414,351.97,39.88,5889
+Rhigmus,5.146,0.0986,31.248,34.50,141.99,5907
+Kathywhaler,3.539,0.0899,38.097,305.42,247.35,5914
+Shouichi,3,0.1132,29.417,231.59,148.76,5922
+Pindarus,3.97,0.1193,30.402,117.43,104.68,5928
+Eetion,5.226,0.0921,40.408,279.70,158.64,6002
+Robbia,3.324,0.1005,29.368,124.98,192.74,6057
+Aulis,5.3,0.0583,59.568,348.72,74.59,6090
+Missing,3.427,0.1952,28.761,119.31,149.61,6103
+Johnfletcher,3.213,0.0632,30.720,212.78,86.03,6137
+Kondojiro,4.769,0.3597,32.492,243.25,96.35,6144
+Missing,3.253,0.1234,27.451,142.61,132.10,6222
+Chikushi,3.934,0.0722,37.4,335.32,207.15,6237
+Univermoscow,3.199,0.0796,28.38,155.40,232.73,6355
+Dubinin,3.205,0.1062,31.902,275.65,39.90,6359
+Walker,3.181,0.1612,42.129,136.91,187.53,6372
+Takashimizuno,3.215,0.1333,25.221,123.09,246.84,6392
+Refugium,3.142,0.1607,29.642,67.11,75.10,6475
+Leitus,5.158,0.0522,50.951,359.92,147.91,6545
+Gvishiani,3.398,0.1921,25.393,189.28,240.47,6574
+Kolya,3.169,0.1858,29.519,116.99,112.27,6619
+Missing,3.186,0.0960,27.930,79.11,119.56,6785
+Masuisakura,3.086,0.2129,26.82,309.57,348.42,6794
+Fukui,3.391,0.0997,29.616,231.44,289.62,6924
+Komatsusakyo,3.214,0.1234,26.889,58.08,228.01,6983
+Lewiscarroll,3.973,0.1869,48.053,192.98,247.94,6984
+Laomedon,5.176,0.1022,37.549,28.04,58.65,6997
+Tithonus,5.178,0.0714,27.828,341.71,259.42,6998
+Hiera,5.13,0.1040,59.150,342.61,123.35,7119
+Longtom,3.178,0.1683,29.896,117.74,290.46,7131
+Euneus,5.154,0.0648,39.770,345.26,306.93,7152
+Semois,3.994,0.1757,25.526,112.21,290.16,7174
+Hypsenor,5.127,0.0376,47.731,14.28,128.11,7352
+Xanthomalitia,3.926,0.0352,32.471,226.45,190.64,7394
+Prylis,5.2,0.0646,42.893,17.76,207.16,7543
+Missing,3.21,0.1458,37.034,44.41,260.75,7588
+Cindygraber,3.152,0.0737,38.463,25.72,271.37,7605
+Cteatus,5.216,0.0541,71.839,289.20,227.43,7641
+Dolon,5.267,0.0600,42.516,262.32,218.66,7815
+Kaseda,3.147,0.1515,28.51,279.18,37.20,7895
+Nesvorny,3.049,0.0877,25.143,144.77,164.64,7999
+Anius,5.203,0.0931,37.873,23.89,33.58,8060
+Peterthomas,3.946,0.2078,25.629,60.21,287.62,8086
+Tyndareus,5.196,0.0485,27.088,49.66,57.77,8125
+Agrius,5.157,0.0429,27.174,136.21,265.91,8241
+Eurysaces,5.309,0.0464,26.210,93.67,116.06,8317
+Missing,3.989,0.1981,27.689,253.69,257.79,8376
+Asbolus,18.04,0.6211,66,91.41,290.64,8405
+AMOS,3.886,0.0283,49.91,239.77,85.11,8721
+Sawaishujiro,3.93,0.0511,30.135,28.68,327.15,8915
+Tianjindaxue,3.408,0.1191,37.122,68.28,169.57,8917
+Mnesthus,5.217,0.0655,49.151,306.76,159.45,9023
+Othryoneus,5.312,0.0159,32.186,212.50,13.28,9030
+Rhesus,5.161,0.1309,42.306,316.30,173.75,9142
+Erichthonios,5.261,0.0545,27.532,352.02,311.61,9430
+Pytho,5.116,0.0866,38.358,14.81,185.63,9431
+Hohmann,3.958,0.2339,27.664,352.90,288.11,9661
+Lycomedes,5.082,0.0380,31.736,341.24,59.26,9694
+Nauplius,5.228,0.1283,33.423,311.20,274.42,9712
+Deipyrus,5.242,0.0559,32.771,12.75,152.58,9790
+Thronium,5.19,0.0486,68.033,25.99,115.41,9799
+Eurymachos,5.197,0.0047,28.076,268.94,102.14,9818
+Murillo,3.949,0.1269,25.941,224.63,4.29,9829
+Hecamede,5.161,0.0262,49.518,124.74,6.77,9857
+Malytheatre,3.144,0.1148,25.855,344.30,244.46,10007
+Chariklo,15.82,0.1677,302,103.26,242.87,10199
+Amphiaraos,5.278,0.0072,26.826,314.55,325.68,10247
+Mameta,3.995,0.2557,25.184,52.42,258.23,10608
+Phemios,5.196,0.0311,30.963,316.41,231.89,10664
+Missing,3.935,0.0685,33.20,269.47,173.28,10889
+Missing,5.181,0.0204,37.047,118.25,18.42,11089
+Laertes,5.14,0.0315,41.093,355.29,327.70,11252
+Missing,5.194,0.0909,25.570,308.13,217.41,11275
+Leucus,5.298,0.0654,34.155,11.98,160.41,11351
+Iphinous,5.214,0.0677,68.977,71.20,119.53,11395
+Missing,5.215,0.0650,37.109,32.49,177.77,11396
+Missing,5.261,0.0630,45.431,21.78,151.29,11397
+Alcinoos,5.33,0.0144,32.354,343.95,57.52,11428
+Demodokus,5.236,0.0313,37.630,286.09,91.39,11429
+Missing,5.149,0.0485,32.139,298.06,6.46,11487
+Thersilochos,5.175,0.1438,49.960,299.88,128.50,11509
+Solikamsk,3.949,0.2400,29.686,211.73,49.29,11542
+Boucolion,5.274,0.1534,51.136,334.63,182.24,11552
+Asios,5.279,0.0651,41.561,35.42,127.67,11554
+Missing,5.134,0.1281,31.327,324.79,89.12,11663
+Missing,5.233,0.0434,26.794,321.60,159.56,11869
+Echemmon,5.181,0.0927,31.190,289.22,111.56,11887
+Angel,3.201,0.1578,27.233,327.02,220.74,11911
+Aretaon,5.227,0.0693,39.151,311.12,87.19,12052
+Missing,5.215,0.2094,53.202,335.00,304.47,12126
+Imranakperov,3.2,0.1074,25.452,66.66,82.30,12235
+Actor,5.174,0.1250,30.252,2.51,177.86,12238
+Koon,5.107,0.0685,37.861,337.73,93.41,12242
+Yoshitoki,3.171,0.0334,27.53,269.68,73.73,12365
+Prothoon,5.238,0.0725,63.835,354.49,65.76,12444
+Missing,3.203,0.0363,30.143,149.11,275.20,12559
+Buckjean,2.984,0.0692,25.76,97.93,17.88,12583
+Ascanios,5.155,0.1487,25.102,330.87,342.16,12649
+Peiraios,5.175,0.0580,26.458,353.34,325.51,12658
+Alkimos,5.239,0.0367,47.819,314.92,161.91,12714
+Missing,5.241,0.0939,32.174,328.07,273.81,12921
+Periboea,5.244,0.0404,54.077,330.41,128.73,12929
+Missing,3.975,0.1595,27.435,127.53,211.56,13035
+Missing,5.148,0.1240,36.148,16.90,97.51,13060
+Podarkes,5.175,0.0119,28.958,60.10,285.17,13062
+Missing,5.214,0.1138,30.901,24.65,66.65,13182
+Missing,5.221,0.0905,41.483,89.21,315.53,13183
+Augeias,5.177,0.0494,33.962,95.68,99.12,13184
+Echion,5.261,0.0746,27.554,271.65,166.30,13229
+Dannymeyer,3.161,0.0119,31.63,171.55,329.17,13244
+Missing,5.179,0.0275,28.324,220.22,118.03,13362
+Missing,5.223,0.1053,33.302,308.67,355.80,13366
+Missing,5.24,0.0484,25.420,8.82,304.43,13372
+Missing,5.233,0.0459,36.053,82.55,167.82,13385
+Antiphos,5.191,0.0080,25.326,8.94,86.33,13463
+Missing,5.265,0.0705,29.285,23.12,164.18,13694
+Missing,3.365,0.1122,37.543,59.16,127.55,13832
+Neely,3.113,0.1987,26.385,115.45,186.55,13860
+Missing,5.14,0.0853,28.530,357.89,25.33,14235
+Missing,5.214,0.0921,57.54,333.50,127.77,14268
+Missing,5.211,0.0321,43.169,43.79,6.93,14690
+Missing,5.239,0.0417,25.942,354.45,286.29,14707
+Masanoriabe,3.198,0.0223,25.708,349.27,340.24,14962
+Missing,5.177,0.2036,33.292,345.93,165.09,15033
+Missing,3.217,0.2020,35.539,172.53,99.82,15161
+Paquet,3.985,0.2163,25.417,231.14,64.33,15278
+Missing,5.132,0.0256,35.516,263.59,315.55,15398
+Dexius,5.211,0.0452,87.646,332.15,179.07,15436
+Eioneus,5.294,0.0233,62.519,350.05,283.98,15440
+Missing,5.122,0.0149,53.100,147.04,180.08,15502
+Missing,5.244,0.0695,27.941,231.95,170.86,15521
+Missing,5.212,0.1545,36.433,60.52,168.83,15527
+Missing,5.182,0.0850,39.767,319.77,302.17,15535
+Missing,5.208,0.1442,28.974,321.95,258.90,15536
+Missing,5.269,0.0456,42.208,293.73,333.41,15539
+Missing,3.151,0.1961,29.594,300.07,217.63,15562
+Missing,3.993,0.1852,32.265,174.05,224.61,15638
+Periphas,5.198,0.1055,36.200,18.44,24.01,15663
+Missing,39.74,0.1886,328,72.45,318.44,15789
+Missing,5.176,0.0474,43.530,191.36,227.65,15977
+Charops,5.139,0.1260,63.191,358.88,353.76,16070
+Missing,5.187,0.0830,36.774,30.69,278.12,16099
+Missing,3.102,0.0195,25.982,199.72,176.49,16133
+Missing,3.192,0.1016,27.713,318.52,83.06,16461
+Daitor,5.059,0.0421,43.861,24.40,159.87,16560
+Missing,5.198,0.2003,35.390,298.75,239.31,16667
+Missing,3.156,0.0983,31.056,245.13,90.00,16785
+Missing,5.223,0.1135,38.583,283.76,202.72,16956
+Missing,3.967,0.1126,25.310,102.19,40.81,16970
+Iphthime,5.18,0.0708,57.341,16.59,137.04,16974
+Missing,2.77,0.1708,27.04,244.59,82.67,17109
+Missing,5.137,0.0835,40.946,331.14,356.99,17171
+Missing,5.221,0.0582,34.482,304.14,214.76,17172
+Missing,3.124,0.2243,25.232,260.39,229.37,17252
+Missing,3.173,0.1033,29.731,289.79,18.01,17297
+Caniff,4.002,0.1363,25.368,144.06,118.95,17305
+Aisakos,5.166,0.0737,35.761,199.73,84.91,17314
+Pheidippos,5.16,0.0979,28.749,352.06,46.79,17351
+Missing,5.271,0.0781,44.904,273.31,117.32,17365
+Missing,5.165,0.0838,27.569,292.94,236.35,17417
+Missing,5.223,0.0642,33.138,284.56,330.12,17419
+Charleroi,3.934,0.1145,30.297,16.75,327.30,17428
+Hippasos,5.176,0.0723,53.975,2.46,216.36,17492
+Missing,5.202,0.0587,42.736,315.94,153.09,18046
+Missing,5.243,0.0188,36.222,40.99,129.92,18054
+Zarex,5.124,0.0578,36.431,21.79,154.08,18060
+Missing,5.147,0.0500,30.334,326.48,34.20,18062
+Missing,5.157,0.0580,31.122,24.82,65.10,18063
+Missing,5.103,0.0161,33.664,198.08,203.84,18137
+Drymas,5.178,0.0686,28.885,32.88,208.44,18278
+Missing,3.102,0.0851,27.533,282.43,16.36,18331
+Demoleon,5.288,0.0933,33.474,322.90,90.17,18493
+Missing,5.216,0.1003,32.111,304.65,122.25,19018
+Missing,5.209,0.1138,42.613,321.83,224.71,19020
+Missing,5.146,0.0740,31.668,309.35,36.21,19725
+Missing,3.071,0.0631,47.698,20.21,114.07,19737
+Missing,5.194,0.0505,37.972,339.31,103.64,19844
+Varuna,42.76,0.0578,900,118.82,264.39,20000
+Missing,5.19,0.0108,27.467,219.39,154.28,20144
+Missing,5.208,0.1307,45.804,326.30,4.87,20424
+Missing,5.199,0.1470,27.176,341.92,6.22,20428
+Missing,5.23,0.1294,26.367,20.05,271.97,20716
+Missing,5.284,0.1467,34.120,304.14,351.93,20720
+Missing,5.218,0.0652,50.961,7.30,92.92,20729
+Missing,5.207,0.1371,27.043,279.12,183.51,20739
+Fountainhills,4.287,0.4688,37.31,124.02,236.35,20898
+Missing,5.094,0.1154,26.203,330.01,10.80,20995
+Pandion,5.217,0.1026,28.550,27.32,183.89,21284
+Missing,5.194,0.0738,29.196,291.80,48.08,21370
+Missing,5.206,0.1356,35.178,6.45,258.28,21595
+Missing,5.205,0.1175,28.312,334.09,210.99,21599
+Missing,5.234,0.0357,54.909,325.40,209.45,21601
+Orus,5.124,0.0377,50.810,323.10,180.38,21900
+Missing,5.153,0.1065,39.487,298.70,202.37,22014
+Missing,5.179,0.0370,27.680,346.60,322.99,22052
+Missing,5.199,0.0528,34.000,259.11,230.44,22054
+Missing,5.259,0.0257,31.816,107.26,215.10,22055
+Missing,5.192,0.1092,25.376,241.04,320.81,22059
+Missing,5.167,0.0444,48.190,257.46,225.64,22149
+Missing,5.177,0.0712,39.753,242.67,145.45,22180
+Missing,5.198,0.1724,33.744,333.86,320.41,23075
+Missing,3.141,0.1143,29.213,328.20,11.64,23099
+Missing,5.256,0.1327,32.954,25.98,63.08,23119
+Missing,5.339,0.0592,25.883,325.67,124.80,23123
+Pheidas,5.266,0.0504,66.230,272.14,253.68,23135
+Missing,4.002,0.1244,28.210,31.24,102.08,23186
+Missing,5.109,0.0562,29.690,307.01,132.79,23285
+Missing,5.177,0.0485,26.310,263.87,270.57,23463
+Missing,5.206,0.0854,27.621,178.44,302.52,23480
+Missing,5.228,0.1624,27.292,333.67,235.38,23624
+Missing,5.217,0.0373,32.389,311.08,225.13,23694
+Missing,5.231,0.0999,46.001,302.12,234.54,23958
+Missing,5.255,0.1619,31.358,301.80,28.76,23968
+Missing,5.266,0.0670,32.404,312.77,12.26,23970
+Missing,5.192,0.0459,35.342,328.60,164.39,24244
+Missing,5.122,0.0440,28.389,268.35,216.78,24275
+Missing,5.249,0.1062,25.545,53.68,291.05,24312
+Missing,5.264,0.0865,34.591,6.51,356.94,24313
+Dorippe,5.261,0.0830,31.607,13.81,35.81,24380
+Missing,5.259,0.0561,25.380,274.20,342.71,24390
+Missing,5.278,0.0286,29.392,304.69,326.79,24403
+Missing,3.159,0.1898,25.004,123.36,301.03,24440
+Missing,5.227,0.0814,31.392,270.08,68.61,24446
+Missing,5.155,0.0536,25.907,272.23,198.34,24448
+Missing,5.284,0.1303,40.666,285.43,323.63,24451
+Missing,5.16,0.0549,27.932,330.55,356.65,24453
+Missing,5.072,0.0326,28.224,302.29,258.28,24454
+Missing,5.224,0.0925,25.686,24.25,3.17,24458
+Missing,5.262,0.1192,28.326,316.00,6.99,24459
+Missing,5.238,0.0853,33.067,331.66,67.35,24470
+Missing,5.318,0.0455,29.125,257.38,139.20,24471
+Missing,5.192,0.0445,28.723,287.72,136.39,24472
+Missing,5.145,0.0426,26.422,64.06,191.56,24485
+Missing,5.18,0.0763,33.157,71.04,140.81,24486
+Missing,5.24,0.0496,31.888,76.70,349.07,24505
+Missing,5.323,0.0304,39.052,298.80,124.97,24506
+Missing,5.22,0.0876,26.279,273.89,137.14,24519
+Missing,5.141,0.1193,25.883,9.59,249.90,24530
+Missing,5.211,0.0833,29.913,85.97,306.18,24534
+Missing,5.173,0.0829,31.158,10.07,15.13,24537
+Kapaneus,5.184,0.0100,25.738,256.84,340.60,24587
+Missing,5.243,0.0724,28.649,284.77,164.21,25347
+Missing,5.149,0.0235,29.842,37.96,30.46,25883
+Missing,5.217,0.0749,33.195,168.00,167.98,25895
+Missing,3.097,0.2137,27.139,288.88,56.11,29564
+Missing,5.141,0.0347,32.512,323.15,190.71,29603
+Missing,3.12,0.1548,40.347,121.67,26.24,29943
+Missing,5.162,0.0090,33.952,231.01,102.69,29976
+Missing,5.223,0.0894,33.098,343.48,156.37,29977
+Missing,5.26,0.0419,36.422,82.86,282.98,30102
+Missing,5.224,0.0627,29.232,56.98,287.87,30504
+Missing,5.208,0.0811,25.838,257.00,195.50,30505
+Missing,5.126,0.0819,34.356,291.78,11.33,30506
+Phegeus,5.252,0.0404,27.002,354.73,283.49,30704
+Idaios,5.194,0.0606,44.546,260.00,342.12,30705
+Echepolos,5.203,0.0127,25.351,220.59,19.16,30708
+Helicaon,5.2,0.0650,32.544,244.52,270.26,30942
+Missing,5.225,0.0774,47.396,348.55,191.80,31342
+Agathon,5.345,0.0386,40.645,279.48,325.97,31344
+Missing,5.248,0.0096,29.730,28.48,286.88,31819
+Elatus,11.76,0.3850,57.000,209.83,281.65,31824
+Missing,5.131,0.0527,26.904,349.18,350.94,31835
+Missing,3.186,0.0961,26.399,238.11,74.11,32253
+Missing,5.216,0.1099,27.968,191.37,274.32,32339
+Missing,5.239,0.0093,30.763,345.47,170.39,32397
+Missing,5.216,0.1264,30.829,356.13,344.10,32435
+Missing,5.197,0.1241,28.865,338.26,30.37,32437
+Missing,5.16,0.0284,29.252,349.88,352.59,32440
+Missing,5.217,0.0999,26.879,307.96,65.20,32451
+Missing,5.243,0.0160,30.260,153.48,263.91,32464
+Missing,5.209,0.0963,38.365,333.85,286.62,32475
+Missing,5.244,0.0930,29.583,301.66,207.34,32480
+Missing,5.141,0.0278,27.868,12.79,220.12,32482
+Missing,5.278,0.0795,48.017,313.96,274.24,32496
+Missing,5.17,0.1624,38.923,314.51,245.48,32499
+Missing,5.218,0.0697,35.619,51.35,180.49,32501
+Thereus,10.6,0.2002,86.500,237.49,87.25,32532
+Missing,5.158,0.0336,36.180,281.56,226.21,32615
+Apisaon,5.279,0.0783,28.249,83.42,159.84,32811
+Missing,5.1,0.0746,28.921,324.25,318.34,34521
+Missing,5.213,0.0988,33.306,324.27,266.67,34642
+Thoon,5.157,0.0388,61.684,338.40,197.59,34746
+Missing,5.142,0.0397,29.077,341.48,90.14,34785
+Missing,5.157,0.0761,25.296,55.26,358.70,35276
+Missing,5.09,0.0439,34.836,0.34,359.16,35673
+Missing,5.182,0.0923,39.393,73.73,10.30,36267
+Missing,5.314,0.1010,30.752,317.99,7.20,36279
+Missing,5.16,0.0225,32.117,327.66,346.58,36624
+Missing,5.25,0.0767,26.879,264.59,255.45,37297
+Missing,5.162,0.1029,25.017,313.90,128.46,37299
+Missing,5.181,0.0527,27.099,254.43,167.52,37301
+Amphios,5.21,0.0072,33.076,323.63,292.83,37519
+Bias,5.198,0.0777,61.603,328.03,192.86,38050
+Missing,5.229,0.0127,29.497,185.22,303.76,38610
+Missing,5.248,0.0717,35.944,359.58,206.57,39264
+Missing,5.166,0.0577,33.218,150.70,262.54,39369
+Missing,5.266,0.0895,26.068,345.97,220.28,39474
+Missing,5.162,0.0580,34.950,294.34,285.54,41340
+Missing,5.12,0.0615,31.006,328.10,343.04,41379
+Missing,5.207,0.0324,38.322,131.65,257.18,42187
+Typhon,37.62,0.5339,192.000,24.55,158.77,42355
+Missing,5.22,0.0430,32.160,262.51,341.34,42367
+Missing,5.127,0.0289,27.397,87.08,134.01,42554
+Missing,3.379,0.0816,27.208,324.01,152.53,43390
+Missing,3.343,0.2010,27.818,9.25,88.73,44566
+Missing,5.276,0.0857,26.634,314.81,154.86,47957
+Missing,5.263,0.0297,26.772,342.29,105.91,47963
+Missing,5.149,0.0300,36.052,278.67,287.11,48438
+Missing,5.19,0.0911,28.043,227.08,303.92,48764
+Missing,5.191,0.0547,27.121,280.86,21.96,51350
+Missing,5.149,0.1078,28.731,323.00,58.80,51354
+Missing,5.275,0.0987,27.850,200.14,6.05,51364
+Missing,5.217,0.0573,40.606,354.59,257.58,51365
+Missing,5.166,0.0868,26.350,319.75,298.74,51910
+Missing,5.109,0.1104,27.223,324.56,277.76,51958
+Missing,5.189,0.0579,27.479,25.89,302.65,51962
+Ophelestes,5.292,0.0255,25.070,328.45,200.88,52767
+Okyrhoe,8.375,0.3034,36.000,209.17,337.51,52872
+Missing,5.149,0.0947,25.302,0.33,129.88,53418
+Missing,5.058,0.0119,28.399,350.21,299.98,53436
+Bienor,16.49,0.2001,187.500,327.94,152.70,54598
+Missing,5.289,0.0792,37.743,357.09,178.65,54656
+Missing,5.106,0.0476,28.643,1.67,178.32,55060
+Missing,5.255,0.0465,31.406,344.23,167.82,55419
+Missing,5.135,0.0456,26.631,41.21,54.02,55563
+Missing,5.127,0.0349,27.608,39.70,321.47,55568
+Amycus,25.12,0.3919,100.900,54.21,239.63,55576
+Missing,5.203,0.0361,25.865,140.33,258.48,56968
+Missing,5.229,0.0247,28.255,207.71,316.89,57714
+Missing,5.176,0.0423,25.338,196.87,340.18,58008
+Palmys,5.258,0.0998,27.753,14.81,134.57,58931
+Missing,5.279,0.0725,34.916,90.56,71.24,60383
+Echeclus,10.73,0.4574,59.000,69.05,163.21,60558
+Missing,5.23,0.0778,26.466,77.31,351.93,62426
+Missing,5.216,0.1259,29.767,156.92,259.37,63273
+Missing,5.208,0.0263,28.373,44.09,88.34,68444
+Missing,5.286,0.0144,27.855,33.09,121.44,68519
+Missing,5.264,0.0945,33.098,320.01,256.57,76857
+Missing,5.167,0.0305,42.849,300.51,298.10,76867
+Missing,5.198,0.1478,28.432,347.69,346.18,80119
+Missing,5.237,0.0785,29.391,97.29,72.50,90337
+Missing,23.17,0.2226,230.500,7.48,156.01,95626
+Missing,5.322,0.0858,26.242,340.62,217.84,99334
+Missing,5.252,0.0573,30.603,318.56,187.43,117447
+Missing,20.8,0.4715,82.000,58.43,116.74,120061
+Missing,65.87,0.6819,170.000,9.04,27.63,127546
+Missing,5.284,0.0692,26.632,23.95,156.65,128299
+Missing,5.232,0.0878,28.299,52.18,55.51,134720
+Missing,5.282,0.0959,25.881,29.65,35.69,134749
+Missing,5.268,0.0488,26.039,320.39,60.27,134957
+Missing,20.06,0.2564,118.000,43.51,70.00,136204
+Missing,28.87,0.6748,37.700,26.95,90.69,148975
+Missing,5.254,0.0880,27.048,8.99,14.71,159342
+Missing,22.16,0.4608,78.440,40.16,70.82,248835
+Missing,12.54,0.3152,38.900,102.71,99.31,250112
+Missing,14.69,0.3087,58.000,50.25,141.72,281371
+Missing,15.81,0.3789,39.100,109.19,134.23,309139
+Missing,29.83,0.5641,110.060,26.28,108.39,310071
+Missing,13.2,0.3063,44.200,90.32,136.41,328884
+Missing,12.74,0.4461,33.000,66.18,240.43,332685
+Missing,279.6,0.9663,44.200,0.86,132.79,336756
+Missing,11.58,0.4418,67.100,99.59,330.35,342842
+Missing,35.2,0.6783,28.500,22.53,246.12,413666
+Missing,385.1,0.9841,46.400,0.46,178.90,"2010 BK118"
+Missing,21.62,0.5603,26.900,46.86,238.70,"2010 ES65"
+Missing,24.5,0.7621,28.000,35.14,314.29,"2010 FH92"
+Missing,18.57,0.3246,69.900,79.80,210.41,"2010 TH"
+Missing,53.44,0.6496,112.700,14.68,292.88,"2010 WG9"
+Missing,21.28,0.4734,63.700,62.50,7.59,"2011 MM4"
+Schwassmann-Wachmann,6,0.0436,60.4,197.11,50.64,29P
+Swift-Tuttle,26.09,0.9632,26,7.63,152.98,109P
+CINEOS,16.14,0.2700,66.170,16.20,343.65,167P
+Hale-Bopp,182.1,0.9950,60,1.68,130.66,"1995 O1"
+Spacewatch,38.41,0.8729,55.100,0.10,180.60,"2011 KP36"
diff --git a/data/sol_planets.csv b/data/sol_planets.csv
new file mode 100644
index 0000000..819f9c4
--- /dev/null
+++ b/data/sol_planets.csv
@@ -0,0 +1,9 @@
+Mercury,Sol,0.387098,0.205630,0.055,0.3829,174.796,29.124
+Venus,Sol,0.723332,0.006772,0.815,0.9499,50.115,54.884
+Earth,Sol,1.0,0.0167086,1.0,1.0,358.617,114.20783
+Mars,Sol,1.523680,0.0934,0.107,0.533,19.412,286.5
+Jupiter,Sol,5.2038,0.0483,317.8,10.973,20.020,273.867
+Saturn,Sol,9.5826,0.0565,95.159,9.1402,317.020,339.392
+Uranus,Sol,19.19126,0.04717,14.536,4.0,142.2386,96.998857
+Neptune,Sol,30.07,0.008678,17.147,3.883,256.228,273.187
+Pluto,Sol,39.482,0.2488,0.00218,0.1868,14.53,113.834
diff --git a/data/sol_satellites.csv b/data/sol_satellites.csv
new file mode 100644
index 0000000..993eb9d
--- /dev/null
+++ b/data/sol_satellites.csv
@@ -0,0 +1,211 @@
+Luna,Earth,0.00257,0.0549,0.0123,0.2727,128.0,128.0
+Hydra,Pluto,0.000432493,0.006,8.02782e-09,0.00290378,330.6,143.4
+Charon,Pluto,0.000131018,0,0.00026562,0.0951185,192.4,0
+Neso,Neptune,0.334536,0.447,0,0,123.2,338.3
+Sao,Neptune,0.14961,0.299,0,0,179.6,90.9
+Hippocamp,Neptune,0.000703887,0.001,0,0,286.5,346.4
+Proteus,Neptune,0.000786107,0,6.48101e-06,0.0326479,276.8,0
+Galatea,Neptune,0.000414444,0,4.76401e-07,0.0123999,86.7,0
+Despina,Neptune,0.000350941,0,2.9284e-07,0.0116151,125.1,0
+Ferdinand,Uranus,0.138023,0.397,0,0,256.7,79.1
+Trinculo,Uranus,0.0568524,0.219,0,0,88.5,130.1
+Caliban,Uranus,0.0483296,0.204,0,0,224.9,8.3
+Cupid,Uranus,0.000497333,0.005,0,0,160.6,13.5
+Mab,Uranus,0.000653084,0.003,0,0,348,237.9
+Perdita,Uranus,0.000510702,0.002,0,0,32.2,310.4
+Belinda,Uranus,0.000503349,0,0,0,121.3,0
+Rosalind,Uranus,0.000467253,0,0,0,79.4,0
+Juliet,Uranus,0.000430487,0.001,0,0,124.8,291.5
+Cressida,Uranus,0.000413107,0,0,0,332.8,0
+Bianca,Uranus,0.000395728,0.001,0,0,236.2,97
+Cordelia,Uranus,0.000332892,0,0,0,95,0
+Puck,Uranus,0.000574874,0,0,0,174.5,0
+Miranda,Uranus,0.000868328,0.001,1.07874e-05,0.0370115,72.4,155.6
+Ophelia,Uranus,0.000359631,0.011,0,0,280.5,344.3
+Titania,Uranus,0.00291649,0.001,0.000569223,0.123827,53.2,202
+Ariel,Uranus,0.00127609,0.001,0.000209476,0.0908649,119.8,83.3
+S2019_s01,Saturn,0.0751749,0.463,0,0,36.6,86.6
+Portia,Uranus,0.000441851,0,0,0,343.7,0
+S2007_s02,Saturn,0.111753,0.179,0,0,84.1,57.7
+S2006_s03,Saturn,0.149922,0.379,0,0,167.1,188.7
+S2004_s39,Saturn,0.155089,0.102,0,0,98,199.8
+S2004_s38,Saturn,0.148839,0.541,0,0,101.4,346.6
+S2004_s36,Saturn,0.15668,0.617,0,0,138.8,204.4
+S2004_s33,Saturn,0.157629,0.514,0,0,128.3,309.7
+S2004_s29,Saturn,0.114106,0.488,0,0,183.8,318.9
+S2004_s28,Saturn,0.146011,0.161,0,0,95.9,186.6
+S2004_s26,Saturn,0.174515,0.147,0,0,153.2,151.7
+S2004_s24,Saturn,0.156058,0.072,0,0,289.6,181
+S2004_s22,Saturn,0.137689,0.216,0,0,102.8,118.9
+S2007_s03,Saturn,0.126593,0.185,0,0,292.7,111.9
+S2004_s21,Saturn,0.154621,0.409,0,0,187.5,182
+S2004_s27,Saturn,0.132689,0.157,0,0,268.1,142.7
+S2004_s20,Saturn,0.128738,0.182,0,0,122.5,290.1
+S2004_s17,Saturn,0.130002,0.18,0,0,228.5,180.8
+S2004_s13,Saturn,0.123037,0.259,0,0,41.1,346.2
+S2004_s07,Saturn,0.140376,0.529,0,0,79.8,84
+Tarqeq,Saturn,0.120069,0.168,0,0,161,34.8
+Greip,Saturn,0.123377,0.315,0,0,314.5,152.2
+Jarnsaxa,Saturn,0.129373,0.218,0,0,198.7,237.4
+Surtur,Saturn,0.153351,0.446,0,0,136.2,303.7
+Skoll,Saturn,0.118097,0.464,0,0,45,193.1
+Psamathe,Neptune,0.312181,0.451,0,0,70.2,261.3
+Kari,Saturn,0.147683,0.476,0,0,286,163.9
+Margaret,Uranus,0.0940521,0.678,0,0,119.9,90.4
+Hyrrokkin,Saturn,0.123264,0.336,0,0,291.8,273.1
+S2004_s37,Saturn,0.106586,0.446,0,0,185.9,77.2
+Eirene,Jupiter,0.154119,0.258,0,0,329.7,94.8
+S2006_s01,Saturn,0.125537,0.141,0,0,96.6,155
+S2017_j3,Jupiter,0.139982,0.231,0,0,193.3,92.9
+Nereid,Neptune,0.036792,0.749,0,0.0266834,318,290.3
+Chaldene,Jupiter,0.153281,0.265,0,0,266.2,335
+S2011_j2,Jupiter,0.153139,0.355,0,0,284,218.7
+S2010_j1,Jupiter,0.155014,0.252,0,0,161.1,344.2
+Stephano,Uranus,0.0535034,0.218,0,0,190.2,352.6
+Eukelade,Jupiter,0.154196,0.277,0,0,203.6,283.7
+Aoede,Jupiter,0.158947,0.436,0,0,198.8,72.9
+Hegemone,Jupiter,0.156076,0.358,0,0,233.7,282.2
+S2003_j23,Jupiter,0.159289,0.313,0,0,168.5,163.2
+Enceladus,Saturn,0.00159361,0.005,1.80886e-05,0.0395699,57,119.5
+S2004_s35,Saturn,0.146827,0.237,0,0,320.2,154.2
+Kale,Jupiter,0.154097,0.262,0,0,212.7,283.6
+Pallene,Saturn,0.00141914,0.004,0,0,2,194.9
+Sponde,Jupiter,0.157377,0.322,0,0,173.8,184.9
+Calypso,Saturn,0.00197195,0.001,0,0,-0,221.6
+Euporie,Jupiter,0.128784,0.148,0,0,72.2,329.8
+Phobos,Mars,6.28351e-05,0.015,1.77791e-09,0.00173913,189.6,216.3
+Carme,Jupiter,0.154711,0.256,0,0,234,155
+Euanthe,Jupiter,0.13922,0.239,0,0,336.5,169.8
+Francisco,Uranus,0.0286301,0.139,0,0,129.5,297.3
+S2016_j2,Jupiter,0.124963,0.217,0,0,57.6,344.2
+Laomedeia,Neptune,0.157809,0.418,0,0,248.3,146
+S2017_j6,Jupiter,0.155385,0.336,0,0,150.2,100
+Thelxinoe,Jupiter,0.140216,0.228,0,0,267.9,333.4
+Aitne,Jupiter,0.154176,0.277,0,0,106,81.3
+Hermippe,Jupiter,0.141102,0.219,0,0,134.7,356.6
+Pasithee,Jupiter,0.152721,0.27,0,0,216,295.2
+Larissa,Neptune,0.000491317,0.001,6.39315e-07,0.0150683,165.5,247.3
+Sycorax,Uranus,0.0814183,0.521,0,0,146.2,211.4
+Deimos,Mars,0.000157088,0,2.41336e-10,0.00097316,205,0
+Fornjot,Saturn,0.168091,0.208,0,0,214.5,324.8
+Naiad,Neptune,0.000322197,0,2.13992e-08,0.00455188,89.7,0
+Janus,Saturn,0.00101271,0.007,3.17651e-07,0.0140009,111.7,11.1
+S2003_j18,Jupiter,0.13594,0.09,0,0,66.1,304.4
+Magaclite,Jupiter,0.158054,0.421,0,0,138.1,85.1
+Triton,Neptune,0.00237169,0,0.00358366,0.212306,63,0
+Himalia,Jupiter,0.0764757,0.16,3.80192e-07,0.0133417,66.5,328.4
+Halimede,Neptune,0.105307,0.566,0,0,173.9,113.5
+Orthosie,Jupiter,0.139715,0.299,0,0,200.7,140.1
+Leda,Jupiter,0.0745091,0.162,0,0,233.4,270.9
+Adrastea,Jupiter,0.000862312,0,3.51217e-10,0.00128708,214.5,0
+Helike,Jupiter,0.139813,0.153,0,0,44.2,118.1
+Loge,Saturn,0.15414,0.186,0,0,337.2,32.8
+Skathi,Saturn,0.104514,0.272,0,0,114.7,203.5
+Bebhionn,Saturn,0.114413,0.468,0,0,168,358.1
+Bergelmir,Saturn,0.129253,0.142,0,0,306.5,133.4
+Io,Jupiter,0.00281956,0.004,0.0149516,0.285903,330.9,49.1
+Amalthea,Jupiter,0.00121258,0.003,4.12831e-07,0.0131063,310.6,180.1
+Nix,Pluto,0.000325539,0,7.52608e-09,0.0028253,84.8,0
+Callisto,Jupiter,0.0125851,0.007,0.0180106,0.378324,87.4,43.8
+Helene,Saturn,0.0025241,0.007,1.20417e-09,0.0028253,-64.5,194.3
+Prometheus,Saturn,0.000931831,0.002,2.68681e-08,0.00676503,135.4,341.9
+Desdemona,Uranus,0.000419124,0,0,0,160.4,0
+Thyone,Jupiter,0.140229,0.233,0,0,244.4,343.5
+S2016_j1,Jupiter,0.139057,0.232,0,0,192.4,197.8
+Iapetus,Saturn,0.0238085,0.028,0.000302335,0.115257,74.8,254.5
+Europa,Jupiter,0.00448603,0.009,0.00803462,0.244985,345.4,45
+S2003_j4,Jupiter,0.153254,0.328,0,0,242.8,194.4
+Fenrir,Saturn,0.150096,0.135,0,0,131.7,121
+Eurydome,Jupiter,0.15307,0.294,0,0,286.3,340.2
+Metis,Jupiter,0.000855627,0,6.27173e-09,0.00337467,166,0
+Isonoe,Jupiter,0.153621,0.249,0,0,124.9,213.5
+Sinope,Jupiter,0.158317,0.264,0,0,167.5,96.6
+Ganymede,Jupiter,0.00715518,0.001,0.0248055,0.412996,324.8,198.3
+Lysithea,Jupiter,0.078215,0.117,0,0,331.5,47.4
+Mimas,Saturn,0.00124333,0.02,6.28049e-06,0.0311097,275.3,160.4
+Praxidike,Jupiter,0.139945,0.246,0,0,112.2,357.2
+S2004_s31,Saturn,0.116974,0.202,0,0,255.4,262.7
+S2017_j9,Jupiter,0.145515,0.2,0,0,261.5,130.7
+Aegaeon,Saturn,0.00111967,0,0,0,4.4,0
+Kallichore,Jupiter,0.153891,0.252,0,0,54.2,310.1
+Siarnaq,Saturn,0.121539,0.28,0,0,201.3,65.9
+Setebos,Uranus,0.116606,0.588,0,0,281.3,214.4
+Autonoe,Jupiter,0.159043,0.33,0,0,145.7,228.3
+Ananke,Jupiter,0.140607,0.237,0,0,259.4,56.2
+Taygete,Jupiter,0.154467,0.253,0,0,95.7,341
+Callirrhoe,Jupiter,0.159063,0.297,0,0,107.1,180.5
+Kore,Jupiter,0.161802,0.328,0,0,31.8,229.3
+Themisto,Jupiter,0.0494559,0.34,0,0,284.7,236.2
+Pasiphae,Jupiter,0.156875,0.412,0,0,277.8,264.8
+Albiorix,Saturn,0.10958,0.48,0,0,32.8,55.9
+Erinome,Jupiter,0.153965,0.276,0,0,265.5,98.2
+Kalyke,Jupiter,0.155768,0.26,0,0,256,130.3
+Mneme,Jupiter,0.13918,0.247,0,0,253.7,18.5
+S2017_j1,Jupiter,0.158724,0.328,0,0,286.5,252.2
+S2017_j8,Jupiter,0.152739,0.255,0,0,350.4,146.9
+S2003_j9,Jupiter,0.155078,0.263,0,0,354.6,199.6
+Titan,Saturn,0.0081679,0.029,0.0225234,0.404137,11.7,78.3
+Eupheme,Jupiter,0.13883,0.241,0,0,359.1,316.6
+Thalassa,Neptune,0.000334898,0,5.91801e-08,0.00627845,165.7,0
+Philophrosyne,Jupiter,0.151102,0.229,0,0,69.5,271.6
+Farbauti,Saturn,0.136299,0.241,0,0,282.8,343
+Methone,Saturn,0.00130149,0.002,0,0,0,315.5
+S2003_j19,Jupiter,0.154791,0.265,0,0,218.4,123.4
+S2017_j2,Jupiter,0.153433,0.272,0,0,293.3,137.5
+Bestla,Saturn,0.134661,0.52,0,0,238.5,81.1
+Pandia,Jupiter,0.0767457,0.179,0,0,153.9,194.3
+S2004_s34,Saturn,0.161433,0.282,0,0,34.7,346.5
+S2004_s25,Saturn,0.140049,0.519,0,0,208,268.2
+S2010_j2,Jupiter,0.138993,0.248,0,0,306.3,15.1
+S2017_j5,Jupiter,0.155124,0.257,0,0,66.9,211.7
+S2017_j7,Jupiter,0.140141,0.233,0,0,359.1,119.4
+Carpo,Jupiter,0.113921,0.416,0,0,339.8,86.6
+Ersa,Jupiter,0.076211,0.116,0,0,263.4,304.7
+Mundilfari,Saturn,0.124688,0.21,0,0,92.8,309.7
+Elara,Jupiter,0.0782919,0.211,0,0,330.7,140.1
+S2011_j1,Jupiter,0.154578,0.271,0,0,248.4,251.8
+Arche,Jupiter,0.154399,0.261,0,0,39.8,213.5
+S2003_j10,Jupiter,0.157598,0.264,0,0,286.9,227.5
+S2003_j2,Jupiter,0.140361,0.225,0,0,35.2,200.4
+S2004_s32,Saturn,0.141392,0.254,0,0,169.4,32.7
+S2003_j12,Jupiter,0.14013,0.235,0,0,201.3,277.9
+S2003_j16,Jupiter,0.139592,0.243,0,0,307.4,24.6
+Polydeuces,Saturn,0.0025241,0.019,0,0,359,94.1
+Herse,Jupiter,0.154752,0.262,0,0,141.2,101.2
+Cyllene,Jupiter,0.158122,0.419,0,0,121.3,47.8
+S2003_j24,Jupiter,0.152993,0.259,0,0,131.8,24.2
+Tethys,Saturn,0.00197195,0.001,0.000103392,0.0833621,0,335.3
+Harpalyke,Jupiter,0.139655,0.232,0,0,219.3,71.3
+Narvi,Saturn,0.12934,0.43,0,0,114.2,170
+Dione,Saturn,0.00252477,0.002,0.000183426,0.088118,212,116
+Rhea,Saturn,0.00352411,0.001,0.000386193,0.11984,31.5,44.3
+Umbriel,Uranus,0.0017781,0.004,0.00021349,0.0917752,258.3,157.5
+Thebe,Jupiter,0.00148331,0.018,7.56371e-08,0.00773819,182.1,26.6
+Pandora,Saturn,0.000947206,0.004,2.32305e-08,0.00637263,123.9,217.9
+S2004_s23,Saturn,0.143431,0.437,0,0,65.1,22.8
+Aegir,Saturn,0.138712,0.252,0,0,26,242.7
+Hyperion,Saturn,0.00990322,0.105,9.29446e-07,0.0211898,122.9,214
+Prospero,Uranus,0.108738,0.439,0,0,125.3,251.9
+S2004_s30,Saturn,0.138444,0.087,0,0,336.5,269.3
+Phoebe,Saturn,0.0864277,0.164,1.3918e-06,0.0167164,308,240.3
+Telesto,Saturn,0.00197195,0.001,0,0,360,66.2
+S2004_s12,Saturn,0.13293,0.327,0,0,1.6,87.1
+Epimetheus,Saturn,0.00101205,0.02,8.81555e-08,0.00913514,197.2,96.3
+Oberon,Uranus,0.00389979,0.001,0.000515035,0.11951,139.7,182.4
+Atlas,Saturn,0.000920468,0.001,9.28217e-10,0.00237011,289.1,82.3
+Pan,Saturn,0.000893061,0,7.02434e-10,0.00219746,146.6,0
+Daphnis,Saturn,0.000912446,0,0,0,153.6,0
+Anthe,Saturn,0.00132422,0.002,0,0,351.4,293.4
+Dia,Jupiter,0.081955,0.232,0,0,309.6,176.8
+Ymir,Saturn,0.154601,0.334,0,0,228.7,21.4
+Kerberos,Pluto,0.000386369,0,2.75956e-09,0.000941767,303.5,0
+Kiviuq,Saturn,0.0758233,0.212,0,0,171,90.6
+Ijiraq,Saturn,0.0762578,0.272,0,0,17.3,92.9
+Paaliaq,Saturn,0.101378,0.341,0,0,321.3,238.7
+Tarvos,Saturn,0.121947,0.538,0,0,265.8,274.1
+Iocaste,Jupiter,0.140822,0.227,0,0,215.5,244.7
+Suttungr,Saturn,0.130136,0.114,0,0,321.1,34.3
+Erriapus,Saturn,0.117662,0.472,0,0,294.8,282.5
+Thrymr,Saturn,0.136486,0.466,0,0,30.1,125.4
+Styx,Pluto,0.000283426,0,0,0.000816198,180.9,0
+Hati,Saturn,0.132809,0.371,0,0,163.6,21.3
diff --git a/include/camera.hpp b/include/camera.hpp
new file mode 100644
index 0000000..9a8bc00
--- /dev/null
+++ b/include/camera.hpp
@@ -0,0 +1,96 @@
+#ifndef CAMERA_HPP
+#define CAMERA_HPP 1
+
+#include "vex.hpp"
+#include "shape.hpp"
+#include "straw.hpp"
+
+#include <vector>
+#include <concepts>
+#include <algorithm>
+
+class Camera;
+struct RenderBatchEntry {
+ shapes::shapes_variant<long> shape;
+ straw::color fg, bg;
+ char c;
+
+ template<class T>
+ constexpr RenderBatchEntry(T Shape) : shape(Shape), fg(straw::WHITE), bg(straw::BLACK), c('#') {}
+ template<class T>
+ constexpr RenderBatchEntry(T Shape, char C) : shape(Shape), fg(straw::WHITE), bg(straw::BLACK), c(C) {}
+ template<class T>
+ constexpr RenderBatchEntry(T Shape, straw::color Fg, char C) : shape(Shape), fg(Fg), bg(straw::BLACK), c(C) {}
+ template<class T>
+ constexpr RenderBatchEntry(T Shape, straw::color Fg, straw::color Bg, char C) : shape(Shape), fg(Fg), bg(Bg), c(C) {}
+
+ void translate(Camera *camera);
+ void plot(Camera *camera);
+private:
+ void plotPoint(shapes::point<long> point, Camera *camera);
+ void plotLine(shapes::line<long> line, Camera *camera);
+ void plotRectangle(shapes::rectangle<long> rectangle, Camera *camera);
+ void plotCircle(shapes::circle<long> circle, Camera *camera);
+ void plotEllipse(shapes::ellipse<long> ellipse, Camera *camera);
+};
+
+class Camera
+{
+ friend struct RenderBatchEntry;
+
+ vex::vec2<long> m_position;
+ vex::vec2<long> m_origin;
+ shapes::rectangle<long> m_frustum;
+
+ std::vector<RenderBatchEntry> m_shapeBatch;
+
+ long m_scale;
+ bool m_dirty;
+
+ straw::screen<char> *m_viewport;
+
+ void updateFrustum();
+
+ template<class T>
+ void translateShape(T &shape);
+public:
+ Camera(straw::screen<char> *viewport) :
+ m_position(0, 0),
+ m_origin(0, 0),
+ m_frustum(0, 0, 0, 0),
+ m_scale(16384),
+ m_dirty(true),
+ m_viewport(viewport) {}
+ ~Camera() {}
+
+ constexpr long getscale() const { return m_scale; }
+ constexpr vex::vec2<long> getpos() const { return m_position; }
+ constexpr vex::vec2<long> getorigin() const { return m_origin; }
+
+ constexpr bool dirty() const { return m_dirty; }
+ void markDirty() { m_dirty = true; }
+
+ void zoom(long by) { m_scale = std::max((unsigned)((int)m_scale + by), (unsigned)1); m_dirty = true; }
+ void setscale(long scale) { m_scale = std::max(scale, (long)1); m_dirty = true; }
+
+ void move(const vex::vec2<long> &pos) { m_position += pos; m_dirty = true; }
+ void move(long x, long y) { move(vex::vec2<long>(x, y)); }
+
+ void setpos(const vex::vec2<long> &pos) { m_position = pos; m_dirty = true; }
+ void setpos(long x, long y) { setpos(vex::vec2<long>(x, y)); }
+
+ void setorigin(const vex::vec2<long> &origin) { m_origin = origin; m_dirty = true; }
+
+ template<class T>
+ void batchShape(T shape) { m_shapeBatch.emplace_back(shape); }
+ template<class T>
+ void batchShape(T shape, char c) { m_shapeBatch.emplace_back(shape, c); }
+ template<class T>
+ void batchShape(T shape, straw::color fg, char c) { m_shapeBatch.emplace_back(shape, fg, c); }
+ template<class T>
+ void batchShape(T shape, straw::color fg, straw::color bg, char c) { m_shapeBatch.emplace_back(shape, fg, bg, c); }
+
+ void draw();
+};
+
+#endif
diff --git a/include/csv.hpp b/include/csv.hpp
new file mode 100644
index 0000000..18e30b0
--- /dev/null
+++ b/include/csv.hpp
@@ -0,0 +1,115 @@
+#ifndef CSV_HPP
+#define CSV_HPP 1
+
+#include <tuple>
+#include <string>
+#include <vector>
+#include <sstream>
+#include <fstream>
+#include <iostream>
+
+namespace csv {
+
+template<char T>
+struct csv_delim : std::ctype<char> {
+ csv_delim() : std::ctype<char>(get_table()) {}
+ static mask const *get_table() {
+ static mask rc[table_size];
+ rc[T] = std::ctype_base::space;
+ rc['\n'] = std::ctype_base::space;
+ return &rc[0];
+ }
+};
+
+template<char Seperator, typename... Vals>
+class CSVFile {
+public:
+ struct CSVLine {
+ std::tuple<Vals...> data;
+
+ CSVLine(const std::string &line) {
+ std::istringstream in(line);
+ in.imbue(std::locale(std::locale(), new csv_delim<Seperator>));
+ read_elements(in, std::make_index_sequence<sizeof...(Vals)>{});
+ }
+
+ template<std::size_t... I>
+ void read_elements(std::istream &in, std::index_sequence<I...>) {
+ std::initializer_list<bool>{read_element(in, std::get<I>(data))...};
+ }
+
+ template<typename T>
+ bool read_element(std::istream &in, T &value) {
+ in >> value; return true;
+ }
+ };
+ struct Reader {
+ private:
+ std::vector<CSVLine> m_lines;
+ public:
+ Reader() {}
+ Reader(CSVFile *parent) {
+ for(std::string line; std::getline(parent->m_rfile, line);) {
+ m_lines.emplace_back(line);
+ }
+ }
+ std::vector<std::tuple<Vals...>> get() const {
+ std::vector<std::tuple<Vals...>> r;
+ for(auto &line : m_lines) r.push_back(line.data);
+ return r;
+ }
+
+ };
+ struct Writer {
+ private:
+ std::vector<std::tuple<Vals...>> m_data;
+ public:
+ void put(std::tuple<Vals...> line) { m_data.push_back(line); }
+ void write(CSVFile *parent) {
+ for(auto &line : m_data) {
+ write_line(parent, line, std::make_index_sequence<sizeof...(Vals)>{});
+ parent->m_wfile.seekp(-1, std::ios_base::end);
+ parent->m_wfile << "\n";
+ }
+ }
+ template<std::size_t... I>
+ void write_line(CSVFile *parent, std::tuple<Vals...> line, std::index_sequence<I...>) {
+ std::initializer_list<bool>{write_element(parent, std::get<I>(line))...};
+ }
+ template<typename T>
+ bool write_element(CSVFile *parent, T &value) {
+ parent->m_wfile << value << Seperator; return true;
+ }
+ };
+
+ friend struct Reader;
+ friend struct Writer;
+
+ CSVFile(const std::string &path, bool write = false) {
+ //std::ios_base::iostate emask = m_file.exceptions() | std::ios::failbit;
+ if(!write) {
+ m_rfile.open(path);
+ m_reader = Reader(this);
+ }else{
+ m_wfile.open(path);
+ }
+ }
+ ~CSVFile() { m_rfile.close(); m_wfile.close(); }
+
+ const std::tuple<Vals...> operator[](std::size_t i) { return m_reader.m_lines[i].data; }
+ std::size_t size() const { return m_reader.m_lines.size(); }
+
+ std::vector<std::tuple<Vals...>> get() const { return m_reader.get(); }
+ void put(std::tuple<Vals...> vals) { m_writer.put(vals); }
+ void write() { m_writer.write(this); }
+
+protected:
+ std::ifstream m_rfile;
+ std::ofstream m_wfile;
+ Reader m_reader;
+ Writer m_writer;
+};
+
+}
+
+#endif
diff --git a/include/ecs.hpp b/include/ecs.hpp
new file mode 100644
index 0000000..ab5e2b2
--- /dev/null
+++ b/include/ecs.hpp
@@ -0,0 +1,139 @@
+#ifndef ECS_HPP
+#define ECS_HPP 1
+
+#include "entitycomponents.hpp"
+#include "util.hpp"
+#include <bitset>
+#include <typeindex>
+#include <queue>
+#include <cassert>
+#include <ranges>
+#include <span>
+#include <iostream>
+
+namespace ecs {
+
+struct ComponentContainer {
+ std::vector<component_variant> packed{};
+ std::vector<int> sparse{};
+ std::queue<unsigned> free{};
+
+ void resize(size_t n) { sparse.resize(n, -1); }
+
+ template<component_type T>
+ void insert(unsigned id, const T &c) {
+ assert(sparse.size() > id);
+ if(free.empty()) {
+ sparse[id] = (int)packed.size();
+ packed.push_back(c);
+ }else {
+ sparse[id] = (int)free.front();
+ packed[sparse[id]] = c;
+ free.pop();
+ }
+ }
+
+ void remove(unsigned id) {
+ assert(sparse.size() > id);
+ if(sparse[id] > -1) {
+ free.push((unsigned)sparse[id]);
+ }
+ sparse[id] = -1;
+ }
+
+ template<component_type T>
+ T &reduce(unsigned id) {
+ assert(sparse.size() > id);
+ assert(sparse[id] > -1);
+ return std::get<T>(packed[sparse[id]]);
+ }
+};
+
+class EntityMan;
+struct Entity {
+ EntityMan *man;
+ component_sig sig{};
+ unsigned id;
+
+ Entity(const Entity &e) = default;
+ Entity(EntityMan *Man, unsigned Id) :
+ man(Man), sig(0), id(Id) {}
+
+
+ template<component_type T>
+ constexpr bool contains() { return sig.test(get_index<T, component_variant>()); }
+
+ template<component_type T>
+ T &get();
+
+ template<component_type T>
+ Entity &addComponent(const T &component);
+};
+
+class EntityMan {
+ std::array<ComponentContainer, std::variant_size_v<component_variant>> m_components;
+ std::vector<Entity> m_entities;
+ std::queue<unsigned> m_free;
+public:
+ Entity &operator[](std::size_t i) { return m_entities[i]; }
+
+ Entity newEntity() {
+ std::size_t newid = 0;
+ if(!m_free.empty()) {
+ newid = m_free.front();
+ m_free.pop();
+ }else{
+ newid = m_entities.size();
+ m_entities.emplace_back(this, newid);
+ for(auto &container : m_components) container.resize(m_entities.size());
+ }
+ return m_entities[newid];
+ }
+
+ void deleteEntity(Entity &e) {
+ for(auto &container : m_components) container.remove(e.id);
+ e.sig.reset();
+ m_free.push(e.id);
+ }
+
+ template<component_type T>
+ T &get(const Entity &e) {
+ constexpr unsigned cid = get_index<T, component_variant>();
+ return m_components[cid].reduce<T>(e.id);
+ }
+
+ template<component_type T>
+ auto getWith() {
+ constexpr unsigned cid = get_index<T, component_variant>();
+ auto e_hc = [](Entity const e) { return e.sig[cid]; };
+ return std::ranges::views::filter(m_entities, e_hc);
+ }
+
+ std::span<Entity> all() {
+ return std::span<Entity>(m_entities.begin(), m_entities.end());
+ }
+
+ std::size_t size() { return m_entities.size(); }
+
+ template<component_type T>
+ Entity &addComponent(Entity &entity, const T& component) {
+ constexpr unsigned cid = get_index<T, component_variant>();
+ m_components[cid].insert(entity.id, component);
+ m_entities[entity.id].sig[cid] = 1;
+ return entity;
+ }
+};
+
+template<component_type T>
+T &Entity::get() {
+ return man->get<T>(*this);
+}
+
+template<component_type T>
+Entity &Entity::addComponent(const T& component) {
+ return man->addComponent(*this, component);
+}
+
+}
+
+#endif
diff --git a/include/entitycomponents.hpp b/include/entitycomponents.hpp
new file mode 100644
index 0000000..a263ebf
--- /dev/null
+++ b/include/entitycomponents.hpp
@@ -0,0 +1,58 @@
+#ifndef ENTITY_COMPONENT_HPP
+#define ENTITY_COMPONENT_HPP 1
+
+#include "vex.hpp"
+#include "units.hpp"
+#include <bitset>
+
+namespace ecs {
+struct PositionComponent {
+ vex::vec2<long> position{};
+};
+
+struct VelocityComponent {
+ vex::vec2<long> velocity{};
+};
+
+struct MassComponent {
+ unit::Mass mass;
+};
+
+struct NameComponent {
+ std::string name;
+};
+
+struct OrbitalComponent {
+ unsigned origin;
+ long a;
+ double e;
+ double w;
+ double M;
+ double T;
+ double v;
+};
+
+struct RenderCircleComponent {
+ unsigned radius;
+};
+
+using component_variant = std::variant<
+ std::monostate,
+ PositionComponent,
+ VelocityComponent,
+ MassComponent,
+ NameComponent,
+ OrbitalComponent,
+ RenderCircleComponent
+>;
+
+using component_sig =
+ std::bitset<std::variant_size_v<component_variant>>;
+
+template<typename T>
+concept component_type =
+ is_variant_v<T, component_variant>;
+
+}
+
+#endif
diff --git a/include/game.hpp b/include/game.hpp
new file mode 100644
index 0000000..9454318
--- /dev/null
+++ b/include/game.hpp
@@ -0,0 +1,52 @@
+#ifndef GAME_HPP
+#define GAME_HPP 1
+
+#include "window.hpp"
+#include "camera.hpp"
+#include "ecs.hpp"
+#include "system.hpp"
+#include "timeman.hpp"
+#include "input.hpp"
+
+#include <memory>
+
+#define WINCTX_GAME "Game"
+
+class Game
+{
+public:
+ enum class State {
+ STOPPED, RUNNING, RUNNING_INPUT, PAUSED, PAUSED_INPUT
+ };
+
+ static void setup(unsigned w, unsigned h);
+ static void cleanup();
+
+ static void turn();
+ static void setState(State state) { m_state = state; }
+ static void setContext(const std::string &id) { m_currentContext = id; }
+
+ static bool running() { return m_state != State::STOPPED; }
+ static bool paused() { return m_state == State::PAUSED || m_state == State::PAUSED_INPUT; }
+ static bool inputMode() { return m_state == State::RUNNING_INPUT || m_state == State::PAUSED_INPUT; }
+
+ struct WindowContexts {
+ WindowContext &operator[](const std::string &id) { return Game::m_contexts.at(id); }
+ WindowContext &operator()() { return Game::m_contexts.at(Game::m_currentContext); }
+ };
+ static WindowContexts contexts;
+private:
+ static std::unordered_map<std::string, WindowContext> m_contexts;
+ static std::string m_currentContext;
+
+ static std::unique_ptr<Camera> m_camera;
+ static std::unique_ptr<System> m_system;
+ static SystemView m_systemView;
+
+ static input::Context m_inputContext;
+
+ static double m_delta;
+ static State m_state;
+};
+
+#endif
diff --git a/include/input.hpp b/include/input.hpp
new file mode 100644
index 0000000..ed5155c
--- /dev/null
+++ b/include/input.hpp
@@ -0,0 +1,71 @@
+#ifndef INPUT_HPP
+#define INPUT_HPP 1
+
+namespace input
+{
+
+enum extkeys {
+ CTRL_RANGE_START = 256,
+ CTRL_KEY_ARROWUP = 321,
+ CTRL_KEY_ARROWDOWN,
+ CTRL_KEY_ARROWRIGHT,
+ CTRL_KEY_ARROWLEFT,
+ CTRL_KEY_END = 326,
+ CTRL_KEY_HOME = 328,
+ CTRL_KEY_PAGEUP,
+ CTRL_KEY_PAGEDOWN
+};
+
+#ifdef __unix__
+#include <termios.h>
+#include <unistd.h>
+
+class Context
+{
+ struct termios m_termold;
+ struct termios m_termnow;
+public:
+ Context() {
+ tcgetattr(STDIN_FILENO, &m_termold);
+ m_termnow = m_termold;
+ }
+ ~Context() {
+ tcsetattr(STDIN_FILENO, TCSADRAIN, &m_termold);
+ }
+
+ void echo(bool mode) {
+ if(mode){
+ m_termnow.c_lflag |= ECHO;
+ }else{
+ m_termnow.c_lflag &= ~ECHO;
+ }
+ tcsetattr(STDIN_FILENO, TCSANOW, &m_termnow);
+ }
+
+ void canon(bool mode) {
+ if(mode) {
+ m_termnow.c_lflag |= ICANON;
+ }else{
+ m_termnow.c_lflag &= ~ICANON;
+ }
+ tcsetattr(STDIN_FILENO, TCSANOW, &m_termnow);
+ }
+
+ void cbreak(bool mode) {
+ if(mode){
+ m_termnow.c_cc[VMIN] = m_termold.c_cc[VMIN];
+ m_termnow.c_cc[VTIME] = m_termold.c_cc[VTIME];
+ }else{
+ m_termnow.c_cc[VMIN] = 1;
+ m_termnow.c_cc[VTIME] = 0;
+ }
+ tcsetattr(STDIN_FILENO, TCSANOW, &m_termnow);
+ }
+};
+
+#endif
+
+extern int getcode();
+}
+
+#endif
diff --git a/include/keybind.hpp b/include/keybind.hpp
new file mode 100644
index 0000000..6541a21
--- /dev/null
+++ b/include/keybind.hpp
@@ -0,0 +1,71 @@
+#ifndef KEYBIND_HPP
+#define KEYBIND_HPP 1
+
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <unordered_map>
+
+#define CTX_GLOBAL "Global"
+#define CTX_SYSTEMVIEW "System View"
+#define CTX_TIMEMAN "Time Manager"
+
+#define BIND_G_QUIT "G_Quit"
+#define BIND_G_NEXTWIN "G_NextWindow"
+#define BIND_G_PREVWIN "G_PrevWindow"
+#define BIND_G_EDITBINDS "G_EditBinds"
+#define BIND_G_ESCAPE "G_Escape"
+#define BIND_G_SELECT "G_Select"
+
+#define BIND_SYSTEMVIEW_PANUP "Systemview_PanUp"
+#define BIND_SYSTEMVIEW_PANDOWN "Systemview_PanDown"
+#define BIND_SYSTEMVIEW_PANLEFT "Systemview_PanLeft"
+#define BIND_SYSTEMVIEW_PANRIGHT "Systemview_PanRight"
+#define BIND_SYSTEMVIEW_DECSCALE "Systemview_DecScale"
+#define BIND_SYSTEMVIEW_INCSCALE "Systemview_IncScale"
+#define BIND_SYSTEMVIEW_SEARCH "Systemview_Search"
+
+#define BIND_SYSTEMVIEW_SEARCH_PREV "Systemview_Search_Prev"
+#define BIND_SYSTEMVIEW_SEARCH_NEXT "Systemview_Search_Next"
+#define BIND_SYSTEMVIEW_SEARCH_TOP "Systemview_Search_Top"
+#define BIND_SYSTEMVIEW_SEARCH_BOTTOM "Systemview_Search_Bottom"
+#define BIND_SYSTEMVIEW_SEARCH_COLLAPSE "Systemview_Search_Collapse"
+
+#define BIND_TIMEMAN_STEP "Timeman_Step"
+#define BIND_TIMEMAN_INCSTEP "Timeman_IncStep"
+#define BIND_TIMEMAN_DECSTEP "Timeman_DecStep"
+#define BIND_TIMEMAN_TOGGLEAUTO "Timeman_ToggleAuto"
+
+class KeyMan {
+public:
+ struct Bind {
+ int code;
+ std::string name;
+ std::string ctx;
+ std::string desc;
+ };
+
+ struct Binds {
+ std::vector<Bind> operator()() {
+ std::vector<Bind> bindList;
+ std::transform(
+ KeyMan::m_keybinds.begin(),
+ KeyMan::m_keybinds.end(),
+ std::back_inserter(bindList), [](auto &pair){return pair.second;});
+ return bindList;
+ }
+ Bind &operator[](const std::string &name) { return KeyMan::m_keybinds[name]; }
+ };
+ static Binds binds;
+
+ static void registerBind(int def, const std::string &name, const std::string &context, const std::string &desc);
+ static void loadKeybindsFrom(const std::string &csvPath);
+ static void writeKeybindsTo(const std::string &csvPath);
+ static std::string translateCode(int code);
+
+private:
+ static std::unordered_map<std::string, Bind> m_keybinds;
+ static std::unordered_map<std::string, std::string> m_keybindContexts;
+};
+
+#endif
diff --git a/include/shape.hpp b/include/shape.hpp
new file mode 100644
index 0000000..0d9db96
--- /dev/null
+++ b/include/shape.hpp
@@ -0,0 +1,197 @@
+#ifndef SHAPE_HPP
+#define SHAPE_HPP 1
+
+#include "vex.hpp"
+#include <iostream>
+#include <variant>
+
+namespace shapes {
+
+template<vex::arithmetic T>
+struct shape
+{
+ vex::vec2<T> position;
+
+ constexpr shape(const vex::vec2<T> p) : position(p) {}
+ constexpr shape(T x, T y) : position(x, y) {}
+
+ virtual void scale(T by) = 0;
+ virtual void translate(vex::vec2<T> by) { position += by; }
+};
+
+template<vex::arithmetic T>
+struct point : public shape<T>
+{
+ constexpr point(T x, T y) : shape<T>(vex::vec2<T>(x, y)) {}
+ constexpr point(const vex::vec2<T> &pos) : shape<T>(pos) {}
+
+ void scale(T by) override { (void)by; }
+};
+
+template<vex::arithmetic T>
+struct line : public shape<T>
+{
+ vex::vec2<T> end;
+ constexpr line(T x, T y, T z, T w) : shape<T>(vex::vec2<T>(x, y)), end(z, w){}
+ constexpr line(const vex::vec2<T> &pos, const vex::vec2<T> End) : shape<T>(pos), end(End) {}
+
+ void translate(vex::vec2<T> by)
+ {
+ this->position += by;
+ end += by;
+ }
+ void scale(T by) override {
+ end = vex::vec2<T>(
+ (T)std::floor((double)end[0] / (double)by),
+ (T)std::floor((double)end[1] / (double)by));
+ }
+};
+
+template<vex::arithmetic T>
+struct circle : public shape<T>
+{
+ T radius;
+ constexpr circle(T x, T y, T r) : shape<T>(vex::vec2<T>(x, y)), radius(r) {}
+ constexpr circle(const vex::vec2<T> &pos, T r) : shape<T>(pos), radius(r) {}
+
+ void scale(T by) override { radius /= by; }
+};
+
+template<vex::arithmetic T>
+struct ellipse : public shape<T>
+{
+ T a, b;
+ constexpr ellipse(T x, T y, T A, T B) : shape<T>(x, y), a(A), b(B) {}
+ constexpr ellipse(const vex::vec2<T> &pos, T A, T B) : shape<T>(pos), a(A), b(B) {}
+
+ void scale(T by) override {a /= by; b /= by; }
+};
+
+template<vex::arithmetic T>
+struct rectangle : public shape<T>
+{
+ vex::vec2<T> bounds;
+ constexpr rectangle(T x, T y, T w, T h) : shape<T>(vex::vec2<T>(x, y)), bounds(w, h) {}
+ constexpr rectangle(const vex::vec2<T> &pos, const vex::vec2<T> &wh) : shape<T>(pos), bounds(wh) {}
+
+ void scale(T by) override { bounds /= by; }
+};
+
+template<vex::arithmetic T>
+using shapes_variant = std::variant<
+ point<T>, line<T>, circle<T>, ellipse<T>, rectangle<T>
+>;
+
+template<vex::arithmetic L, vex::arithmetic R>
+static bool
+intersects(const circle<L> &lhs, const point<R> &rhs)
+{
+ vex::vec2<L> dist = rhs.position - lhs.position;
+ //std::cout << dist.magnitude() << ' ' << lhs.radius << ' ' << dist.magnitude() - lhs.radius << std::endl;
+ return dist.magnitude() < lhs.radius;
+}
+template<vex::arithmetic L, vex::arithmetic R>
+static bool intersects(const point<L> &lhs, const circle<R> &rhs) { return intersects(rhs, lhs); }
+
+template<vex::arithmetic L, vex::arithmetic R>
+static bool
+intersects(const ellipse<L> &lhs, const point<R> &rhs)
+{
+ auto ds = lhs.position - rhs.position;
+ auto d2 = ds * ds;
+ L a2 = lhs.a * lhs.a;
+ L b2 = lhs.b * lhs.b;
+
+ return (((double)d2[0] / a2) + ((double)d2[1] / b2)) <= 1;
+}
+template<vex::arithmetic L, vex::arithmetic R>
+static bool intersects(const point<L> &lhs, const ellipse<R> &rhs) { return intersects(rhs, lhs); }
+
+template<vex::arithmetic L, vex::arithmetic R>
+static bool
+intersects(const rectangle<L> &lhs, const point<R> &rhs)
+{
+ vex::vec2<L> corner = lhs.position + lhs.bounds;
+ return (rhs.position[0] > lhs.position[0] && rhs.position[0] < corner[0] &&
+ rhs.position[1] > lhs.position[1] && rhs.position[1] < corner[1]);
+}
+template<vex::arithmetic L, vex::arithmetic R>
+static bool intersects(const point<L> &lhs, const rectangle<R> &rhs) { return intersects(rhs, lhs); }
+
+template<vex::arithmetic L, vex::arithmetic R>
+static bool
+intersects(const line<L> &lhs, const line<R> &rhs)
+{
+ double x1 = lhs.position[0], x2 = lhs.end[0], x3 = rhs.position[0], x4 = rhs.end[0];
+ double y1 = lhs.position[1], y2 = lhs.end[1], y3 = rhs.position[1], y4 = rhs.end[1];
+ double uA = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
+ double uB = ((x2-x1)*(y1-y3) - (y2-y1)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
+
+ if(uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) return true;
+ return false;
+}
+
+template<vex::arithmetic L, vex::arithmetic R>
+static bool
+intersects(const rectangle<L> &lhs, const line<R> &rhs)
+{
+ vex::vec2<L> corner = lhs.position + lhs.bounds;
+ line<R> l(lhs.position, lhs.position + vex::vec2<R>(0, lhs.bounds[1]));
+ line<R> r(lhs.position + vex::vec2<R>(lhs.bounds[0], 0), corner);
+ line<R> d(lhs.position, lhs.position + vex::vec2<R>(lhs.bounds[0], 0));
+ line<R> u(lhs.position + vex::vec2<R>(0, lhs.bounds[1]), corner);
+
+ if(intersects(rhs, l) || intersects(rhs, r) || intersects(rhs, d) || intersects(rhs, u)) return true;
+ return (rhs.position[0] > lhs.position[0] && rhs.position[0] < corner[0] &&
+ rhs.position[1] > lhs.position[1] && rhs.position[1] < corner[1]) &&
+ (rhs.end[0] > lhs.position[0] && rhs.end[0] < corner[0] &&
+ rhs.end[1] > lhs.position[1] && rhs.end[1] < corner[1]);
+}
+template<vex::arithmetic L, vex::arithmetic R>
+static bool intersects(const line<L> &lhs, const rectangle<R> &rhs) { return intersects(rhs, lhs); }
+
+template<vex::arithmetic L, vex::arithmetic R>
+static bool
+intersects(const rectangle<L> &lhs, const circle<R> &rhs)
+{
+ vex::vec2<L> dist{
+ rhs.position[0] - std::max(lhs.position[0], std::min(rhs.position[0], lhs.position[0] + lhs.bounds[0])),
+ rhs.position[1] - std::max(lhs.position[1], std::min(rhs.position[1], lhs.position[1] + lhs.bounds[1])),
+ };
+ return (dist[0] * dist[0]) + (dist[1] * dist[1]) < (rhs.radius * rhs.radius);
+}
+template<vex::arithmetic L, vex::arithmetic R>
+static bool intersects(const circle<L> &lhs, const rectangle<R> &rhs) { return intersects(rhs, lhs); }
+
+template<vex::arithmetic L, vex::arithmetic R>
+static bool
+intersects(const rectangle<L> &lhs, const ellipse<R> &rhs)
+{
+ vex::vec2<L> dist{
+ rhs.position[0] - std::max(lhs.position[0], std::min(rhs.position[0], lhs.position[0] + lhs.bounds[0])),
+ rhs.position[1] - std::max(lhs.position[1], std::min(rhs.position[1], lhs.position[1] + lhs.bounds[1])),
+ };
+ vex::vec2<R> ab2 {
+ std::max<R>(1, rhs.a * rhs.a),
+ std::max<R>(1, rhs.b * rhs.b)
+ };
+ return ((dist[0] * dist[0]) / ab2[0]) + ((dist[1] * dist[1]) / ab2[1]) <= 1.0;
+}
+template<vex::arithmetic L, vex::arithmetic R>
+static bool intersects(const ellipse<L> &lhs, const rectangle<R> &rhs) { return intersects(rhs, lhs); }
+
+template<vex::arithmetic L, vex::arithmetic R>
+static bool
+intersects(const rectangle<L> &lhs, const rectangle<R> &rhs)
+{
+ return (
+ (lhs.position[0] < rhs.position[0] + rhs.bounds[0]) &&
+ (lhs.position[0] + lhs.bounds[0] > rhs.position[0]) &&
+ (lhs.position[1] + lhs.bounds[1] < rhs.position[1]) &&
+ (lhs.position[1] > rhs.position[1] + rhs.position[1])
+ );
+}
+
+}
+
+#endif
diff --git a/include/straw.hpp b/include/straw.hpp
new file mode 100644
index 0000000..c147b06
--- /dev/null
+++ b/include/straw.hpp
@@ -0,0 +1,312 @@
+#ifndef STRAW_HPP
+#define STRAW_HPP 1
+
+#include <sstream>
+#include <cstdint>
+#include <cstddef>
+#include <vector>
+#include <span>
+#include <string>
+#include <concepts>
+#include <cassert>
+#include <iostream>
+#include <algorithm>
+
+namespace straw
+{
+
+struct color {
+ std::uint8_t r{}, g{}, b{};
+ constexpr color(std::uint8_t R, std::uint8_t G, std::uint8_t B) : r(R), g(G), b(B) {}
+ constexpr color(std::uint8_t A) : r(A), g(A), b(A) {}
+
+ constexpr uint32_t single() { return (uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b; }
+
+ constexpr bool operator==(const color &o) const = default;
+};
+
+static constexpr color WHITE{255, 255, 255};
+static constexpr color BLACK{0, 0, 0};
+
+struct attribs {
+ color bg{0, 0, 0}, fg{255, 255, 255};
+ bool bold, underline;
+ constexpr attribs() = default;
+ constexpr attribs(color Fg) : fg(Fg) {}
+ constexpr attribs(color Bg, color Fg) : bg(Bg), fg(Fg) {}
+ constexpr attribs(color Bg, color Fg, bool B, bool U) : bg(Bg), fg(Fg), bold(B), underline(U) {}
+
+ constexpr bool operator==(const attribs &o) const = default;
+};
+
+template<typename T>
+concept char_type = std::integral<T>;
+
+template<char_type chartype>
+struct cell {
+ chartype chr{};
+ attribs attr{};
+
+ constexpr cell() = default;
+ constexpr cell(chartype Chr) : chr(Chr) {}
+ constexpr cell(chartype Chr, color Fg) : chr(Chr), attr(Fg) {}
+ constexpr cell(chartype Chr, color Bg, color Fg) : chr(Chr), attr(Bg, Fg) {}
+ constexpr cell(chartype Chr, color Bg, color Fg, bool B, bool U) : chr(Chr), attr(Bg, Fg, B, U) {}
+ constexpr cell(chartype Chr, attribs Attr) : chr(Chr), attr(Attr) {}
+
+ constexpr bool operator==(const cell &o) const = default;
+};
+
+const std::string ANSI_ESCAPE = "\E[";
+static void ANSI_MOVE(unsigned x, unsigned y) { std::cout << ANSI_ESCAPE << y+1 << ';' << x+1 << 'H' << std::flush; }
+static void ANSI_COLOR_FG(color c) { std::cout << ANSI_ESCAPE << "38;2;" << (unsigned)c.r << ';' << (unsigned)c.g << ';' << (unsigned)c.b << 'm' << std::flush; }
+static void ANSI_COLOR_BG(color c) { std::cout << ANSI_ESCAPE << "48;2;" << (unsigned)c.r << ';' << (unsigned)c.g << ';' << (unsigned)c.b << 'm' << std::flush; }
+
+class screen_command_base {};
+
+template<char_type chartype>
+class screen {
+public:
+ explicit screen(unsigned X, unsigned Y, unsigned W, unsigned H, chartype C, color B, color F) :
+ m_x(X), m_y(Y), m_width(W), m_height(H), m_front(W * H, cell{C, B, F}), m_back(m_front),
+ m_cursorAttribs(B,F), m_fillChar(C)
+ {
+ redraw();
+ }
+
+ explicit screen(unsigned X, unsigned Y, unsigned W, unsigned H, chartype C) :
+ screen(X, Y, W, H, C, color{0, 0, 0}, color{255, 255, 255}) {}
+ explicit screen(unsigned X, unsigned Y, unsigned W, unsigned H) :
+ screen(X, Y, W, H, ' ') {}
+
+ constexpr void setcursorxy(unsigned x, unsigned y) { m_cursorX = x; m_cursorY = y; }
+ constexpr void setcursorfg(uint8_t r, uint8_t g, uint8_t b) { m_cursorAttribs.fg = color{r, g, b}; }
+ constexpr void setcursorbg(uint8_t r, uint8_t g, uint8_t b) { m_cursorAttribs.bg = color{r, g, b}; }
+ constexpr void setcursorfg(color c) { m_cursorAttribs.fg = c; }
+ constexpr void setcursorbg(color c) { m_cursorAttribs.bg = c; }
+ constexpr void setcursorbold(bool bold) { m_cursorAttribs.bold = bold; }
+ constexpr void setcursorunderline(bool underline) { m_cursorAttribs.underline = underline; }
+
+ constexpr unsigned getcursorx() { return m_cursorX; }
+ constexpr unsigned getcursory() { return m_cursorY; }
+ constexpr unsigned getx() { return m_x; }
+ constexpr unsigned gety() { return m_y; }
+ constexpr unsigned getwidth() { return m_width; }
+ constexpr unsigned getheight() { return m_height; }
+
+ void clear(const chartype c) { std::fill(m_front.begin(), m_front.end(), cell{c, m_cursorAttribs}); }
+
+ void clearrow(unsigned y, const chartype c) {
+ assert(y < m_height);
+ std::fill(m_front.begin() + (y * m_width),
+ m_front.begin() + (y * m_width) + m_width,
+ cell{c, m_cursorAttribs});
+ }
+
+ void scroll() {
+ m_cursorY = m_height - 1;
+ std::copy(m_front.begin() + m_width, m_front.end(), m_front.begin());
+ std::fill(m_front.end() - m_width, m_front.end(), cell{m_fillChar, m_cursorAttribs});
+ }
+
+ void setc(unsigned x, unsigned y, chartype c) {
+ assert(x < m_width);
+ assert(y < m_height);
+ m_front[x + (y * m_width)] = cell{c, m_cursorAttribs};
+ }
+
+ void putc(chartype c){
+ if(m_cursorY == m_height) {
+ scroll();
+ }
+ switch(c) {
+ case '\n':
+ m_cursorX = 0; m_cursorY++;
+ break;
+ default:
+ (*this)[m_cursorY][m_cursorX++] =
+ cell{c, m_cursorAttribs};
+ break;
+ }
+ if(m_cursorX == m_width) {
+ m_cursorY++;
+ m_cursorX = 0;
+ }
+ }
+
+ void puts(const std::basic_string<chartype> &s){
+ for(const chartype &c : s) this->putc(c);
+ }
+
+ void redraw() {
+ attribs cattr = (*this)[0][0].attr;
+ ANSI_COLOR_BG(cattr.bg);
+ ANSI_COLOR_FG(cattr.fg);
+ for(unsigned y = 0; y < m_height; y++) {
+ ANSI_MOVE(m_x, m_y + y);
+ for(cell c : (*this)[y]) {
+ if(cattr != c.attr) {
+ cattr = c.attr;
+ ANSI_COLOR_FG(cattr.fg);
+ ANSI_COLOR_BG(cattr.bg);
+ }
+ std::cout << c.chr;
+ }
+ std::cout.clear();
+ }
+ m_back = m_front;
+ }
+
+ void flush() {
+ attribs currAttr = m_front[0].attr;
+ ANSI_COLOR_FG(currAttr.fg);
+ ANSI_COLOR_BG(currAttr.bg);
+ for(unsigned y = 0; y < m_height; y++) {
+ auto backspan = std::span<cell<chartype>>(
+ m_back.begin() + (y * m_width),
+ m_back.begin() + (y * m_width) + m_width);
+ auto frontspan = (*this)[y];
+ bool change = false;
+ if(std::equal(backspan.begin(), backspan.end(), frontspan.begin(), frontspan.end())) continue;
+ for(unsigned x = 0; x < m_width; x++) {
+ cell c = frontspan[x];
+ if(c == backspan[x]) continue;
+ ANSI_MOVE(x + m_x, y + m_y);
+ if(c.attr != currAttr) {
+ ANSI_COLOR_FG(c.attr.fg);
+ ANSI_COLOR_BG(c.attr.bg);
+ currAttr = c.attr;
+ }
+ change = true;
+ std::cout << c.chr;
+ }
+ if(change) std::cout.clear();
+ }
+ m_back = m_front;
+ }
+
+ std::span<cell<chartype>> operator[](std::size_t i) {
+ assert(i < m_width * m_height);
+ return std::span<cell<chartype>>(
+ m_front.begin() + (i * m_width),
+ m_front.begin() + (i * m_width) + m_width);
+ }
+
+ template<typename T>
+ requires(!std::is_base_of<screen_command_base, T>::value)
+ friend screen &operator<<(screen &o, const T &rhs) {
+ std::basic_stringstream<chartype> ss;
+ ss << rhs;
+ o.puts(ss.str());
+ return o;
+ }
+
+private:
+ unsigned m_x{}, m_y{};
+ unsigned m_width{}, m_height{};
+
+ std::vector<cell<chartype>> m_front;
+ std::vector<cell<chartype>> m_back;
+
+ unsigned m_cursorX{}, m_cursorY{};
+ attribs m_cursorAttribs;
+ chartype m_fillChar;
+};
+
+struct screen_command_flush : public screen_command_base {
+ explicit screen_command_flush() = default;
+ template<char_type T>
+ friend screen<T> &operator<<(screen<T> &o, const screen_command_flush &cmd) {
+ (void)cmd;
+ o.flush();
+ return o;
+ }
+};
+[[nodiscard]] static screen_command_flush flush() { return screen_command_flush{}; }
+
+struct screen_command_redraw : public screen_command_base {
+ explicit screen_command_redraw() = default;
+ template<char_type T>
+ friend screen<T> &operator<<(screen<T> &o, const screen_command_redraw &cmd) {
+ (void)cmd;
+ o.redraw();
+ return o;
+ }
+};
+[[nodiscard]] static screen_command_redraw redraw() { return screen_command_redraw{}; }
+
+template<char_type chartype>
+struct screen_command_clear : public screen_command_base {
+ chartype c;
+ explicit screen_command_clear(chartype C) : c(C) {}
+ friend screen<chartype> &operator<<(screen<chartype> &o, const screen_command_clear &cmd) {
+ o.clear(cmd.c);
+ return o;
+ }
+};
+template<char_type chartype>
+[[nodiscard]] static screen_command_clear<chartype> clear() { return screen_command_clear{chartype{}}; }
+template<char_type chartype>
+[[nodiscard]] static screen_command_clear<chartype> clear(chartype c) { return screen_command_clear{c}; }
+
+struct screen_command_move : public screen_command_base {
+ unsigned x, y;
+ explicit screen_command_move(unsigned X, unsigned Y) : x(X), y(Y) {}
+ template<char_type T>
+ friend screen<T> &operator<<(screen<T> &o, const screen_command_move &cmd) {
+ o.setcursorxy(cmd.x, cmd.y);
+ return o;
+ }
+};
+[[nodiscard]] static screen_command_move move(unsigned x, unsigned y) { return screen_command_move{x, y}; }
+
+template<char_type chartype>
+struct screen_command_plot : public screen_command_base {
+ chartype c;
+ unsigned x, y;
+ explicit screen_command_plot(unsigned X, unsigned Y, chartype C) : c(C), x(X), y(Y) {}
+ friend screen<chartype> &operator<<(screen<chartype> &o, const screen_command_plot &cmd) {
+ o.setc(cmd.x, cmd.y, cmd.c);
+ return o;
+ }
+};
+template<char_type T>
+[[nodiscard]] static screen_command_plot<T> plot(unsigned x, unsigned y, T c) { return screen_command_plot{x, y, c}; }
+
+struct screen_command_recolor : public screen_command_base {
+ color fg, bg;
+ bool rfg, rbg;
+ explicit screen_command_recolor(color Fg, bool side) : fg(Fg), bg(Fg), rfg(side ? true : false), rbg(side ? false : true) {}
+ explicit screen_command_recolor(color Fg, color Bg) : fg(Fg), bg(Bg), rfg(true), rbg(true) {}
+
+ template<char_type T>
+ friend screen<T> &operator<<(screen<T> &o, const screen_command_recolor &cmd) {
+ if(cmd.rbg) o.setcursorbg(cmd.bg);
+ if(cmd.rfg) o.setcursorfg(cmd.fg);
+ return o;
+ }
+};
+[[nodiscard]] static screen_command_recolor setfg(uint8_t r, uint8_t g, uint8_t b) { return screen_command_recolor{color{r, g, b}, true}; }
+[[nodiscard]] static screen_command_recolor setbg(uint8_t r, uint8_t g, uint8_t b) { return screen_command_recolor{color{r, g, b}, false}; }
+[[nodiscard]] static screen_command_recolor setcolor(color fg, color bg) { return screen_command_recolor{fg, bg}; }
+[[nodiscard]] static screen_command_recolor resetcolor() { return screen_command_recolor{WHITE, BLACK}; }
+
+template<char_type chartype>
+struct screen_command_fillrow : public screen_command_base {
+ unsigned row;
+ chartype c;
+
+ friend screen<chartype> &operator<<(screen<chartype> &o, const screen_command_fillrow &cmd) {
+ o.clearrow(cmd.row, cmd.c);
+ return o;
+ }
+};
+
+template<char_type T>
+[[nodiscard]] static screen_command_fillrow<T> fillrow(unsigned row) { return screen_command_fillrow<T>{.row = row, .c = ' '}; }
+template<char_type T>
+[[nodiscard]] static screen_command_fillrow<T> fillrow(unsigned row, T c) { return screen_command_fillrow<T>{.row = row, .c = c}; }
+
+}
+
+#endif
diff --git a/include/system.hpp b/include/system.hpp
new file mode 100644
index 0000000..9de10bc
--- /dev/null
+++ b/include/system.hpp
@@ -0,0 +1,82 @@
+#ifndef SYSTEM_HPP
+#define SYSTEM_HPP 1
+
+#include "ecs.hpp"
+#include "camera.hpp"
+#include "window.hpp"
+
+#include <list>
+
+class System {
+private:
+ friend class SystemView;
+ struct SystemTreeNode {
+ unsigned entityId;
+ std::list<SystemTreeNode> children;
+ };
+ SystemTreeNode m_systemTree;
+ ecs::EntityMan m_entityMan;
+
+ ecs::Entity &addOrbital(const std::string &name, const std::string &orbitingName, unsigned long a, double e, unit::Mass m, unsigned r, double M, double w);
+ void tickOrbitals(unit::Time time);
+
+ SystemTreeNode *traverseSystemTree(SystemTreeNode &node, const std::string &name);
+ SystemTreeNode *getNode(const std::string &name);
+public:
+ System();
+
+ void update();
+
+ ecs::Entity &getBody(std::size_t id);
+};
+
+class SystemView {
+private:
+ System *m_system;
+ System::SystemTreeNode *m_focus;
+
+ class Search {
+ private:
+ struct SystemTreeDisplayNode {
+ System::SystemTreeNode *node;
+ std::list<SystemTreeDisplayNode> children;
+ SystemTreeDisplayNode *parent;
+
+ unsigned index;
+ bool collapsed;
+ bool hidden;
+ };
+ SystemView *m_systemView;
+ SystemTreeDisplayNode m_displayTree;
+ std::vector<SystemTreeDisplayNode*> m_displayTreeFlat;
+
+ unsigned m_selectionIndex;
+ std::string m_query;
+ bool m_dirty;
+
+ void addNodeToTree(SystemTreeDisplayNode &root, System::SystemTreeNode *node);
+ void drawNode(SystemTreeDisplayNode &root, Window &searchWindow, unsigned indent);
+ void rebuild();
+ public:
+ Search(SystemView *systemView);
+
+ void finish();
+ void keypress(int key);
+ void draw();
+ };
+ std::unique_ptr<Search> m_focusSearch;
+public:
+ SystemView(System *system) : m_system(system), m_focusSearch(nullptr) {}
+
+ void keypress(Camera *camera, int key);
+ void update(Camera *camera);
+ void draw(Camera *camera);
+ void drawOver(Camera *camera);
+
+ void view(System *system);
+
+ ecs::Entity &getBody(int id) const;
+ int getBodyIdByName(const std::string &name);
+};
+
+#endif
diff --git a/include/timeman.hpp b/include/timeman.hpp
new file mode 100644
index 0000000..ac5113e
--- /dev/null
+++ b/include/timeman.hpp
@@ -0,0 +1,27 @@
+#ifndef TIME_MANAGER_H
+#define TIME_MANAGER_H 1
+
+#include "util.hpp"
+#include "units.hpp"
+#include "straw.hpp"
+#include "window.hpp"
+
+class TimeMan {
+ static unit::Time m_time;
+ static unit::Time m_step;
+ static bool m_auto;
+ static bool m_changed;
+public:
+
+ static void init();
+
+ static void update(int c);
+ static void draw();
+
+ static unit::Time time() { return m_time; }
+ static bool automatic() { return m_auto; }
+ static void interrupt() { m_auto = false; }
+ static bool changed() { return m_changed; }
+};
+
+#endif
diff --git a/include/units.hpp b/include/units.hpp
new file mode 100644
index 0000000..5f2fd67
--- /dev/null
+++ b/include/units.hpp
@@ -0,0 +1,166 @@
+#ifndef UNIT_HPP
+#define UNIT_HPP 1
+
+#include "util.hpp"
+#include <string>
+
+namespace unit {
+
+constexpr long MINUTE_SECONDS = 60;
+constexpr long HOUR_SECONDS = 3600;
+constexpr long DAY_SECONDS = 86400;
+constexpr long WEEK_SECONDS = 604800;
+constexpr long YEAR_SECONDS = 31556952;
+constexpr long CYEAR_SECONDS = 31536000;
+
+class Mass {
+ double m_kg;
+public:
+ explicit constexpr Mass(double kg) : m_kg(kg) {}
+ constexpr ~Mass() = default;
+
+ constexpr double operator()() { return m_kg; }
+
+ constexpr Mass &operator+=(const Mass &rhs) { this->m_kg += rhs.m_kg; return *this; }
+ constexpr Mass &operator-=(const Mass &rhs) { this->m_kg -= rhs.m_kg; return *this; }
+ constexpr Mass &operator/=(const Mass &rhs) { this->m_kg *= rhs.m_kg; return *this; }
+ constexpr Mass &operator*=(const Mass &rhs) { this->m_kg /= rhs.m_kg; return *this; }
+
+ friend Mass operator+(Mass lhs, const Mass &rhs) { lhs += rhs; return lhs; }
+ friend Mass operator-(Mass lhs, const Mass &rhs) { lhs -= rhs; return lhs; }
+ friend Mass operator*(Mass lhs, const Mass &rhs) { lhs *= rhs; return lhs; }
+ friend Mass operator/(Mass lhs, const Mass &rhs) { lhs /= rhs; return lhs; }
+
+ friend inline bool operator<=>(const Mass &lhs, const Mass &rhs) = default;
+
+ constexpr Mass &operator+=(const double &rhs) { this->m_kg += rhs; return *this; }
+ constexpr Mass &operator-=(const double &rhs) { this->m_kg -= rhs; return *this; }
+ constexpr Mass &operator*=(const double &rhs) { this->m_kg *= rhs; return *this; }
+ constexpr Mass &operator/=(const double &rhs) { this->m_kg /= rhs; return *this; }
+
+ friend Mass operator+(Mass lhs, const double &rhs) { lhs += rhs; return lhs; }
+ friend Mass operator-(Mass lhs, const double &rhs) { lhs -= rhs; return lhs; }
+ friend Mass operator*(Mass lhs, const double &rhs) { lhs *= rhs; return lhs; }
+ friend Mass operator/(Mass lhs, const double &rhs) { lhs /= rhs; return lhs; }
+};
+
+class Time {
+ long m_seconds;
+public:
+ static constexpr unsigned char month_days[12] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ static constexpr unsigned char month_days_leap[12] = {
+ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ static const inline std::string month_str[12] = {
+ "January", "Febuary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
+ };
+
+ explicit constexpr Time(long seconds) : m_seconds(seconds) {}
+
+ constexpr long operator()() { return m_seconds; }
+
+ constexpr Time &operator+=(const Time &rhs) { this->m_seconds += rhs.m_seconds; return *this; }
+ constexpr Time &operator-=(const Time &rhs) { this->m_seconds -= rhs.m_seconds; return *this; }
+ constexpr Time &operator/=(const Time &rhs) { this->m_seconds *= rhs.m_seconds; return *this; }
+ constexpr Time &operator*=(const Time &rhs) { this->m_seconds /= rhs.m_seconds; return *this; }
+
+ friend Time operator+(Time lhs, const Time &rhs) { lhs += rhs; return lhs; }
+ friend Time operator-(Time lhs, const Time &rhs) { lhs -= rhs; return lhs; }
+ friend Time operator*(Time lhs, const Time &rhs) { lhs *= rhs; return lhs; }
+ friend Time operator/(Time lhs, const Time &rhs) { lhs /= rhs; return lhs; }
+
+ friend inline bool operator<=>(const Time &lhs, const Time &rhs) = default;
+
+ constexpr Time &operator+=(const long &rhs) { this->m_seconds += rhs; return *this; }
+ constexpr Time &operator-=(const long &rhs) { this->m_seconds -= rhs; return *this; }
+ constexpr Time &operator*=(const long &rhs) { this->m_seconds *= rhs; return *this; }
+ constexpr Time &operator/=(const long &rhs) { this->m_seconds /= rhs; return *this; }
+
+ friend Time operator+(Time lhs, const long &rhs) { lhs += rhs; return lhs; }
+ friend Time operator-(Time lhs, const long &rhs) { lhs -= rhs; return lhs; }
+ friend Time operator*(Time lhs, const long &rhs) { lhs *= rhs; return lhs; }
+ friend Time operator/(Time lhs, const long &rhs) { lhs /= rhs; return lhs; }
+
+ constexpr bool leap_year() { return (m_seconds % YEAR_SECONDS) % 4 == 0; }
+
+ constexpr Time current_year() {
+ return Time((m_seconds % YEAR_SECONDS) + (m_seconds < 0 ? YEAR_SECONDS : 0));
+ }
+ constexpr Time current_month() {
+ Time year = current_year();
+ if(year.m_seconds < 0) {
+ year.m_seconds = YEAR_SECONDS + year.m_seconds;
+ }
+ unsigned month = 0;
+ const unsigned char *month_days_view = month_days;
+ if(years() % 4 == 0 && years() % 100 == 0 && years() % 400 != 0) month_days_view = month_days_leap;
+ for(month; year.days() > month_days_view[month]; month = (month + 1) % 12) year -= month_days_view[month] * DAY_SECONDS;
+ return year;
+ }
+ constexpr Time current_week() { return Time(m_seconds % WEEK_SECONDS); }
+ constexpr Time current_day() { return Time(m_seconds % DAY_SECONDS); }
+ constexpr Time current_hour() { return Time(m_seconds % HOUR_SECONDS); }
+ constexpr Time current_minute() { return Time(m_seconds % MINUTE_SECONDS); }
+
+ constexpr long seconds() { return m_seconds; }
+ constexpr long minutes() { return m_seconds / MINUTE_SECONDS; }
+ constexpr long hours() { return m_seconds / HOUR_SECONDS; }
+ constexpr long days() { return m_seconds / DAY_SECONDS; }
+ constexpr long weeks() { return m_seconds / WEEK_SECONDS; }
+ constexpr long months() {
+ Time copy(*this);
+ if(copy.m_seconds < 0) {
+ copy.m_seconds = -copy.m_seconds;
+ }
+ unsigned month = 0;
+ const unsigned char *month_days_view = month_days;
+ if(years() % 4 == 0) month_days_view = month_days_leap;
+ for(month; copy.days() > month_days_view[month]; month = (month + 1) % 12) copy -= month_days_view[month] * DAY_SECONDS;
+ return month;
+ }
+ constexpr long years() { return ((m_seconds < 0 ? m_seconds - CYEAR_SECONDS : m_seconds) / CYEAR_SECONDS) + 2000; }
+ constexpr long real_years() { return (m_seconds < 0 ? m_seconds - YEAR_SECONDS : m_seconds) / YEAR_SECONDS; }
+
+ /* %% = '%'
+ * %Y = real year
+ * %C = calendar year
+ * %S = month string
+ * %M = month
+ * %W = week
+ * %D = day
+ * %H = hour
+ * %m = minute
+ * %s = second
+ * */
+ std::string format(const char *fmt);
+};
+
+constexpr long Mm = 1000;
+constexpr long Gm = cxpow_v<long, 10, 6>;
+constexpr long Tm = cxpow_v<long, 10, 9>;
+constexpr long Pm = cxpow_v<long, 10, 12>;
+constexpr long Em = cxpow_v<long, 10, 15>;
+constexpr long Zm = cxpow_v<long, 10, 18>;
+
+constexpr long AU = 149597871;
+
+constexpr Mass kg{1};
+constexpr Mass Mg{cxpow_v<double, 10, 3>};
+constexpr Mass Gg{cxpow_v<double, 10, 6>};
+constexpr Mass Tg{cxpow_v<double, 10, 9>};
+constexpr Mass Pg{cxpow_v<double, 10, 12>};
+constexpr Mass Eg{cxpow_v<double, 10, 15>};
+constexpr Mass Zg{cxpow_v<double, 10, 18>};
+constexpr Mass Yg{cxpow_v<double, 10, 21>};
+
+constexpr Mass lunarMass{7.342 * cxpow_v<double, 10, 22>};
+constexpr Mass earthMass{5.97237 * cxpow_v<double, 10, 24>};
+constexpr Mass jovMass{1.89813 * cxpow_v<double, 10, 27>};
+constexpr Mass solMass{1.98847 * cxpow_v<double, 10, 30>};
+
+constexpr double earthRad = 6371;
+}
+
+#endif
diff --git a/include/util.hpp b/include/util.hpp
new file mode 100644
index 0000000..3c795d1
--- /dev/null
+++ b/include/util.hpp
@@ -0,0 +1,45 @@
+#include <type_traits>
+#ifndef UTIL_HPP
+#define UTIL_HPP 1
+
+#include <variant>
+#include <cstddef>
+
+#if UNICODE == 1
+using screenchr = wchar_t;
+#else
+using screenchr = char;
+#endif
+
+/*Shamelessly stolen from stackoverflow
+ * https://stackoverflow.com/questions/52303316/get-index-by-type-in-stdvariant
+ * by Barry*/
+template <typename> struct tag { };
+template <typename T, typename V>
+struct get_index;
+template <typename T, typename... Ts>
+struct get_index<T, std::variant<Ts...>>
+ : std::integral_constant<size_t, std::variant<tag<Ts>...>(tag<T>()).index()>
+{ };
+
+template<typename T, typename variant_type>
+struct is_variant : std::false_type {};
+template<typename T, typename ... Vs>
+struct is_variant<T, std::variant<Vs...>>
+ : std::disjunction<std::is_same<T, Vs>...> {};
+template<typename T, typename variant_type>
+constexpr bool is_variant_v = is_variant<T, variant_type>::value;
+
+template<typename T, unsigned base, unsigned p>
+struct cxpow { static constexpr T value = (T)base * cxpow<T, base, p - 1>::value; };
+template<typename T, unsigned base>
+struct cxpow<T, base, 0> { static constexpr T value = 1; };
+template<typename T, unsigned base, unsigned p>
+constexpr T cxpow_v = cxpow<T, base, p>::value;
+
+template<typename T, unsigned base, int p>
+struct cxrt { static constexpr T value = (T)base / cxpow<T, base, -p>::value; };
+template<typename T, unsigned base, int p>
+constexpr T cxrt_v = cxrt<T, base, p>::value;
+
+#endif
diff --git a/include/vex.hpp b/include/vex.hpp
new file mode 100644
index 0000000..0a3bb24
--- /dev/null
+++ b/include/vex.hpp
@@ -0,0 +1,104 @@
+#ifndef VEX_H
+#define VEX_H 1
+
+#include <array>
+#include <cmath>
+#include <cstddef>
+#include <ostream>
+#include <concepts>
+
+namespace vex
+{
+
+template<typename T>
+concept arithmetic = std::is_arithmetic<T>::value;
+
+template<arithmetic T, unsigned D>
+ requires (D > 1)
+struct vec_dimd
+{
+ std::array<T, D> v;
+
+ explicit vec_dimd() = default;
+ template<typename ...Args>
+ explicit vec_dimd(Args&&... args) : v{args...} {}
+ explicit vec_dimd(T args[D]) : v(args) {}
+ explicit vec_dimd(T fill) { v.fill(fill); }
+
+ T operator[](std::size_t i) { return v[i]; }
+ T operator[](std::size_t i) const { return v[i]; }
+
+ vec_dimd<T, D> operator+=(const vec_dimd<T, D> &rhs) { for(size_t i = 0; i < D; i++) v[i] += rhs.v[i]; return *this; }
+ vec_dimd<T, D> operator-=(const vec_dimd<T, D> &rhs) { for(size_t i = 0; i < D; i++) v[i] -= rhs.v[i]; return *this; }
+ vec_dimd<T, D> operator*=(const vec_dimd<T, D> &rhs) { for(size_t i = 0; i < D; i++) v[i] *= rhs.v[i]; return *this; }
+ vec_dimd<T, D> operator/=(const vec_dimd<T, D> &rhs) { for(size_t i = 0; i < D; i++) v[i] /= rhs.v[i]; return *this; }
+
+ vec_dimd<T, D> operator*=(const T &rhs) { for(size_t i = 0; i < D; i++) v[i] *= rhs; return *this; }
+ vec_dimd<T, D> operator/=(const T &rhs) { for(size_t i = 0; i < D; i++) v[i] /= rhs; return *this; }
+
+ vec_dimd<T, D> operator-() { return vec_dimd<T,D>(0) - *this; }
+
+ auto operator<=>(const vec_dimd<T,D> &rhs) const { return magnitude() <=> rhs.magnitude(); }
+ bool operator==(const vec_dimd<T,D> &rhs) const { for(unsigned i = 0; i < D; i++) if(v[i] != rhs.v[i]) return false; return true; }
+
+ friend vec_dimd<T, D> operator+(vec_dimd<T, D> lhs, const vec_dimd<T, D> &rhs) { lhs += rhs; return lhs; }
+ friend vec_dimd<T, D> operator-(vec_dimd<T, D> lhs, const vec_dimd<T, D> &rhs) { lhs -= rhs; return lhs; }
+ friend vec_dimd<T, D> operator*(vec_dimd<T, D> lhs, const vec_dimd<T, D> &rhs) { lhs *= rhs; return lhs; }
+ friend vec_dimd<T, D> operator/(vec_dimd<T, D> lhs, const vec_dimd<T, D> &rhs) { lhs /= rhs; return lhs; }
+
+ friend vec_dimd<T, D> operator*(vec_dimd<T, D> lhs, const T &rhs) { lhs *= rhs; return lhs; }
+ friend vec_dimd<T, D> operator/(vec_dimd<T, D> lhs, const T &rhs) { lhs /= rhs; return lhs; }
+
+ friend std::ostream &operator<<(std::ostream &os, const vec_dimd<T,D> obj) {
+ os << '{';
+ for(std::size_t i = 0; i < D; i++) os << obj.v[i] << ((i < (D - 1)) ? ',' : '}');
+ return os;
+ }
+
+ /*Finds the distance from the origin to the ray cast in D dimension space using components of vec*/
+ T sqrMagnitude() const { T t{}; for(size_t i = 0; i < D; i++) t += v[i] * v[i]; return t; }
+ T magnitude() const { return std::sqrt(sqrMagnitude()); }
+
+ /*Finds the dot product of itself and another vec of same T and D*/
+ T dot(const vec_dimd<T, D> &b) const { T t; for(size_t i = 0; i < D; i++) t += (v[i] * b.v[i]); return t; }
+ friend T dot(const vec_dimd<T,D> &lhs, const vec_dimd<T,D> &rhs) { return lhs.dot(rhs); }
+
+ vex::vec_dimd<T, D> normalize() const { return *this / magnitude(); }
+ vex::vec_dimd<T, D> abs() const { vex::vec_dimd<T, D> copy(*this); for(unsigned i = 0; i < D; i++) copy.v[i] = std::abs(copy.v[i]); return copy; }
+
+ auto cross(const vec_dimd<T,D> &o) const {
+ if constexpr(D == 2) return v[0]*o[0] - v[1]*o[1];
+ if constexpr(D == 3) return vec_dimd<T, D>{v[1]*o[2]-v[2]*o[1], v[2]*o[0]-v[0]*o[2],v[0]*o[1]-v[1]*o[0]};
+ }
+};
+
+template<arithmetic T>
+using vec2 = vec_dimd<T, 2>;
+
+template<arithmetic T>
+using vec3 = vec_dimd<T, 3>;
+
+/*(x, y) -> (r, theta)*/
+template<arithmetic R, arithmetic P>
+static vec2<R>
+polar(const vec2<P> &in)
+{
+ return vec2<R>(
+ std::sqrt(in[0] * in[0] + in[1] * in[1]),
+ std::atan2(in[1], in[0])
+ );
+}
+/*(r, theta) -> (x, y)*/
+template<arithmetic R, arithmetic P>
+static vec2<R>
+cartesian(const vec2<P> &in)
+{
+ return vec2<R>(
+ (R)(cos(in[1]) * in[0]),
+ (R)(sin(in[1]) * in[0])
+ );
+}
+
+};
+
+#endif
diff --git a/include/window.hpp b/include/window.hpp
new file mode 100644
index 0000000..78001ea
--- /dev/null
+++ b/include/window.hpp
@@ -0,0 +1,69 @@
+#ifndef WINDOW_HPP
+#define WINDOW_HPP 1
+
+#include "util.hpp"
+#include "straw.hpp"
+#include <memory>
+#include <unordered_map>
+
+//Wrapper for screens that act like windows
+class Window {
+ straw::screen<screenchr> m_border;
+ straw::screen<screenchr> m_screen;
+ std::string m_title;
+ bool m_hidden;
+public:
+ explicit Window(const std::string Title, unsigned X, unsigned Y, unsigned W, unsigned H, bool hidden = false) :
+ m_border(X, Y, W, 1), m_screen(X, Y+1, W, H-1), m_title(Title), m_hidden(hidden) {}
+ ~Window() = default;
+
+ template<typename T>
+ friend Window &operator<<(Window &o, const T &t) {
+ o.m_screen << t;
+ return o;
+ }
+
+ straw::screen<screenchr> *screen() { return &m_screen; }
+ std::string title() const { return m_title; }
+
+ void draw(bool focus);
+
+ void setHidden(bool mode) { m_hidden = mode; }
+ bool hidden() const { return m_hidden; }
+};
+
+#define WINDOW_SYSTEMVIEW_ID "Systemview"
+#define WINDOW_SYSTEMVIEW_SEARCH_ID "SystemviewSearch"
+#define WINDOW_BODYINFO_ID "Bodyinfo"
+#define WINDOW_EVENTS_ID "Events"
+#define WINDOW_TIMEMAN_ID "Timeman"
+
+class WindowContext {
+ std::unordered_map<std::string, Window> m_windows;
+ std::vector<std::string> m_windowOrder;
+ unsigned m_focus;
+public:
+ WindowContext() : m_focus(0) {}
+ ~WindowContext() {}
+
+ void registerWindow(const std::string &id,
+ const std::string &title,
+ unsigned x, unsigned y,
+ unsigned w, unsigned h,
+ bool hidden = false);
+
+ Window &operator[](const std::string &id) { return m_windows.at(id); }
+ Window &operator[](unsigned id) { return m_windows.at(m_windowOrder[id]); }
+ Window &operator()() { return m_windows.at(m_windowOrder[m_focus]); }
+
+ void update(int code);
+ void draw();
+
+ void setWindowHidden(const std::string &id, bool mode);
+ void focus(const std::string &id);
+
+ unsigned getFocused() { return m_focus; }
+ std::string getFocusedString() { return m_windowOrder[m_focus]; }
+};
+
+#endif
diff --git a/src/camera.cpp b/src/camera.cpp
new file mode 100644
index 0000000..59e99a0
--- /dev/null
+++ b/src/camera.cpp
@@ -0,0 +1,197 @@
+#include "camera.hpp"
+#include "shape.hpp"
+#include <cmath>
+#include <algorithm>
+#include <variant>
+#include <typeinfo>
+#include <any>
+
+void
+Camera::updateFrustum(){
+ if(m_dirty) {
+ *m_viewport << straw::clear(' ');
+ m_frustum = shapes::rectangle<long>(0, 0, (long)m_viewport->getwidth(), (long)m_viewport->getheight());
+ m_frustum.position -= (m_frustum.bounds / 2);
+ m_frustum.position += m_position + m_origin;
+ m_dirty = false;
+ }
+}
+
+void
+RenderBatchEntry::translate(Camera *camera)
+{
+ std::visit([camera](auto &shapeval) {
+ shapeval.translate(-camera->m_frustum.position);
+ shapeval.translate((camera->m_frustum.bounds * camera->m_scale) / 2);
+ shapeval.position = vex::vec2<long>(
+ (long)std::floor((double)shapeval.position[0] / (double)camera->m_scale),
+ (long)std::floor((double)shapeval.position[1] / (double)camera->m_scale));
+ shapeval.scale(camera->m_scale);
+ }, shape);
+}
+
+void
+Camera::draw()
+{
+ if(!m_dirty) return;
+ updateFrustum();
+ shapes::rectangle<long> ssfrustum{vex::vec2<long>(0, 0), vex::vec2<long>(m_viewport->getwidth(), m_viewport->getheight())};
+
+ //Remove all batches not intersecting the screenspace frustum
+ m_shapeBatch.erase(
+ std::remove_if(
+ m_shapeBatch.begin(),
+ m_shapeBatch.end(),
+ [ssfrustum, this](RenderBatchEntry &entry){
+ entry.translate(this);
+ return std::visit([ssfrustum](auto &&shape) {
+ return shapes::intersects(shape, ssfrustum) == 0;
+ }, entry.shape);
+ }),
+ m_shapeBatch.end());
+ for(RenderBatchEntry &entry : m_shapeBatch) entry.plot(this);
+ m_shapeBatch.clear();
+}
+
+void
+RenderBatchEntry::plotPoint(shapes::point<long> point, Camera *camera) {
+ long ploty = camera->m_viewport->getheight() - point.position[1];
+ if(point.position[0] < 0 || point.position[0] >= camera->m_viewport->getwidth() ||
+ ploty < 0 || ploty >= camera->m_viewport->getheight()) return;
+ *camera->m_viewport << straw::setcolor(fg, bg) << straw::plot(point.position[0], ploty, c);
+}
+
+void
+RenderBatchEntry::plotLine(shapes::line<long> line, Camera *camera) {
+ if(line.end == line.position) {
+ plotPoint(shapes::point<long>(line.position), camera);
+ }
+ vex::vec2<long> vpdim(camera->m_viewport->getwidth(),
+ camera->m_viewport->getheight());
+ vex::vec2<long> d(line.end - line.position);
+ long adx = std::abs(d[0]);
+ long ady = std::abs(d[1]);
+
+ long offX= d[0] > 0 ? 1 : -1;
+ long offY = d[1] > 0 ? 1 : -1;
+
+ *camera->m_viewport << straw::setcolor(fg, bg);
+ if(adx < ady) {
+ long err = ady / 2;
+ long x = line.position[0];
+ long y = line.position[1];
+ for(long i = 0; i < ady; i++) {
+ if(x > 0 && x < vpdim[0] && y > 0 && y < vpdim[1]) {
+ long ploty = vpdim[1] - y;
+ *camera->m_viewport << straw::plot(x, ploty, c);
+ }
+ if(err >= ady) {
+ x += offX;
+ y += offY;
+ err += adx - ady;
+ }else {
+ y += offY;
+ err += adx;
+ }
+ }
+
+ }else{
+ long err = adx / 2;
+ long x = line.position[0];
+ long y = line.position[1];
+ for(long i = 0; i < adx; i++) {
+ if(x > 0 && x < vpdim[0] && y > 0 && y < vpdim[1]) {
+ long ploty = vpdim[1] - y;
+ *camera->m_viewport << straw::plot(x, ploty, c);
+ }
+ if(err >= adx) {
+ x += offX;
+ y += offY;
+ err += ady - adx;
+ }else {
+ x += offX;
+ err += ady;
+ }
+ }
+ }
+}
+
+void
+RenderBatchEntry::plotCircle(shapes::circle<long> circle, Camera *camera) {
+ if(circle.radius == 1) {
+ plotPoint(shapes::point<long>(circle.position), camera);
+ return;
+ }
+ long sy = std::max<long>(1, circle.position[1] - circle.radius);
+ long ey = std::min<long>(camera->m_viewport->getheight(), circle.position[1] + circle.radius);
+ *camera->m_viewport << straw::setcolor(fg, bg);
+ for(long y = sy; y <= ey; y++) {
+ long ploty = camera->m_viewport->getheight() - y;
+ long r2 = circle.radius * circle.radius;
+ long dy = circle.position[1] - y;
+ long dx = (long)std::sqrt(r2 - (dy * dy));
+ long sx = std::max<long>(0, circle.position[0] - dx + 1);
+ long ex = std::min<long>(camera->m_viewport->getwidth(), circle.position[0] + dx);
+ for(unsigned x = (unsigned)sx; x < ex; x++) {
+ *camera->m_viewport << straw::plot(x, ploty, c);
+ }
+ }
+}
+
+void
+RenderBatchEntry::plotRectangle(shapes::rectangle<long> rectangle, Camera *camera)
+{
+ if(rectangle.bounds[1] == 1) {
+ plotPoint(shapes::point<long>(rectangle.position), camera);
+ return;
+ }
+ long sy = std::max<long>(1, rectangle.position[1]);
+ long ey = std::min<long>(camera->m_viewport->getheight(), rectangle.position[1] + rectangle.bounds[1]);
+ *camera->m_viewport << straw::setcolor(fg, bg);
+ for(long y = sy; y < ey; y++) {
+ long ploty = camera->m_viewport->getheight() - y;
+ long sx = std::max<long>(0, rectangle.position[1]);
+ long ex = std::min<long>(camera->m_viewport->getwidth(), rectangle.position[1] + rectangle.bounds[1]);
+ for(unsigned x = (unsigned)sx; x < ex; x++) {
+ *camera->m_viewport << straw::plot(x, ploty, c);
+ }
+ }
+}
+
+void
+RenderBatchEntry::plotEllipse(shapes::ellipse<long> shapeval, Camera *camera) {
+ if(shapeval.a == 1) {
+ plotPoint(shapes::point<long>(shapeval.position), camera);
+ return;
+ }
+ long sy = std::max<long>(1, shapeval.position[1] - shapeval.b);
+ long ey = std::min<long>(camera->m_viewport->getheight(), shapeval.position[1] + shapeval.b);
+ *camera->m_viewport << straw::setcolor(fg, bg);
+ for(long y = sy; y <= ey; y++) {
+ long ploty = camera->m_viewport->getheight() - y;
+ long dy = shapeval.position[1] - y;
+ long dy2 = dy * dy;
+ long a2 = shapeval.a * shapeval.a;
+ long b2 = shapeval.b * shapeval.b;
+ long dx = (long)(((2.0 * (double)shapeval.a) /
+ (double)shapeval.b) * std::sqrt(b2 - dy2) / 2.0);
+ long sx = std::max<long>(0, shapeval.position[0] - dx + 1);
+ long ex = std::min<long>(camera->m_viewport->getwidth(), shapeval.position[0] + dx);
+
+ for(unsigned x = (unsigned)sx; x < ex; x++) {
+ *camera->m_viewport << straw::plot(x, ploty, c);
+ }
+ }
+}
+void
+RenderBatchEntry::plot(Camera *camera)
+{
+ std::visit([this, camera](auto &shapeval) -> void{
+ using T = std::decay_t<decltype(shapeval)>;
+ if constexpr(std::is_same_v<T, shapes::point<long>>) plotPoint(shapeval, camera);
+ if constexpr(std::is_same_v<T, shapes::line<long>>) plotLine(shapeval, camera);
+ if constexpr(std::is_same_v<T, shapes::ellipse<long>>) plotEllipse(shapeval, camera);
+ if constexpr(std::is_same_v<T, shapes::circle<long>>) plotCircle(shapeval, camera);
+ if constexpr(std::is_same_v<T, shapes::rectangle<long>>) plotRectangle(shapeval, camera);
+ }, shape);
+}
diff --git a/src/game.cpp b/src/game.cpp
new file mode 100644
index 0000000..b1d0b00
--- /dev/null
+++ b/src/game.cpp
@@ -0,0 +1,115 @@
+#include "game.hpp"
+#include "keybind.hpp"
+#include "input.hpp"
+#include <thread>
+#include <chrono>
+
+constexpr static double REQUESTED_FPS = 60.0;
+constexpr static double REQ_FPS_MSPT = 1000.0 / REQUESTED_FPS;
+
+std::unordered_map<std::string, WindowContext> Game::m_contexts;
+std::string Game::m_currentContext;
+
+std::unique_ptr<Camera> Game::m_camera;
+std::unique_ptr<System> Game::m_system;
+SystemView Game::m_systemView(nullptr);
+
+input::Context Game::m_inputContext;
+
+double Game::m_delta;
+Game::State Game::m_state = State::RUNNING;
+Game::WindowContexts Game::contexts;
+
+void
+Game::setup(unsigned w, unsigned h)
+{
+ KeyMan::loadKeybindsFrom("keybinds.csv");
+
+ m_inputContext.echo(false);
+ m_inputContext.canon(false);
+ m_inputContext.cbreak(false);
+
+ unsigned int viewh = h - 1;
+ unsigned int infow = 24;
+ unsigned int infoh = 12;
+ unsigned int timeh = 10;
+
+ TimeMan::init();
+ m_contexts.emplace(WINCTX_GAME, WindowContext());
+ WindowContext *gameContext = &m_contexts[WINCTX_GAME];
+
+ gameContext->registerWindow(WINDOW_SYSTEMVIEW_ID, "System View", infow, 0, w - infow, viewh);
+ gameContext->registerWindow(WINDOW_BODYINFO_ID, "Body Info", 0, 0, infow, infoh);
+ gameContext->registerWindow(WINDOW_EVENTS_ID, "Events", 0, infoh, infow, viewh - infoh - timeh);
+ gameContext->registerWindow(WINDOW_TIMEMAN_ID, "Time", 0, viewh - timeh, infow, timeh);
+
+ gameContext->registerWindow(WINDOW_SYSTEMVIEW_SEARCH_ID, "Search", infow, 0, (w - infow) / 4, viewh, true);
+ m_currentContext = WINCTX_GAME;
+
+ m_camera = std::make_unique<Camera>((*gameContext)[WINDOW_SYSTEMVIEW_ID].screen());
+ m_system = std::make_unique<System>();
+ m_systemView.view(m_system.get());
+
+ KeyMan::registerBind('\x1B', BIND_G_ESCAPE, CTX_GLOBAL, "Escape from focused searchbox / window");
+ KeyMan::registerBind('\n', BIND_G_SELECT, CTX_GLOBAL, "Select something");
+ KeyMan::registerBind('x', BIND_G_NEXTWIN, CTX_GLOBAL, "Change the focused window to the next in the stack");
+ KeyMan::registerBind('X', BIND_G_PREVWIN, CTX_GLOBAL, "Change the focused window to the previous in the stack");
+ KeyMan::registerBind('y', BIND_G_QUIT, CTX_GLOBAL, "Terminate the game");
+
+ KeyMan::registerBind('w', BIND_SYSTEMVIEW_PANUP, CTX_SYSTEMVIEW, "Moves the camera upwards on the system viewer");
+ KeyMan::registerBind('a', BIND_SYSTEMVIEW_PANLEFT, CTX_SYSTEMVIEW, "Moves the camera to the left on the system viewer");
+ KeyMan::registerBind('s', BIND_SYSTEMVIEW_PANDOWN, CTX_SYSTEMVIEW, "Moves the camera downwards on the system viewer");
+ KeyMan::registerBind('d', BIND_SYSTEMVIEW_PANRIGHT, CTX_SYSTEMVIEW, "Moves the camera to the right on the system viewer");
+ KeyMan::registerBind('-', BIND_SYSTEMVIEW_INCSCALE, CTX_SYSTEMVIEW, "Decreases zoom from center of screen");
+ KeyMan::registerBind('+', BIND_SYSTEMVIEW_DECSCALE, CTX_SYSTEMVIEW, "Increases zoom into center of screen");
+ KeyMan::registerBind('/', BIND_SYSTEMVIEW_SEARCH, CTX_SYSTEMVIEW, "Search through bodies in the system");
+
+ KeyMan::registerBind(input::CTRL_KEY_ARROWUP, BIND_SYSTEMVIEW_SEARCH_PREV, CTX_SYSTEMVIEW, "Move the cursor up in the search view");
+ KeyMan::registerBind(input::CTRL_KEY_ARROWDOWN, BIND_SYSTEMVIEW_SEARCH_NEXT, CTX_SYSTEMVIEW, "Move the cursor down in the search view");
+ KeyMan::registerBind(input::CTRL_KEY_HOME, BIND_SYSTEMVIEW_SEARCH_TOP, CTX_SYSTEMVIEW, "Move to first entry in search view");
+ KeyMan::registerBind(input::CTRL_KEY_END, BIND_SYSTEMVIEW_SEARCH_BOTTOM, CTX_SYSTEMVIEW, "Move to last entry in search view");
+ KeyMan::registerBind(input::CTRL_KEY_ARROWRIGHT, BIND_SYSTEMVIEW_SEARCH_COLLAPSE, CTX_SYSTEMVIEW, "Toggle collapsed entry in search view");
+}
+
+void
+Game::cleanup()
+{
+ KeyMan::writeKeybindsTo("keybinds.csv");
+}
+
+void
+Game::turn()
+{
+ auto start = std::chrono::steady_clock::now();
+ auto end = start + std::chrono::milliseconds(16);
+ int c = input::getcode();
+ WindowContext &context = m_contexts.at(m_currentContext);
+
+ /*Global keybinds*/
+ if(!inputMode()) {
+ if(c == KeyMan::binds[BIND_G_QUIT].code) m_state = State::STOPPED;
+ context.update(c);
+ }
+
+ if(m_currentContext == WINCTX_GAME) { /*Game Context*/
+ m_systemView.keypress(m_camera.get(), c);
+
+ m_system->update();
+ m_systemView.update(m_camera.get());
+ TimeMan::update(c);
+ if(TimeMan::changed()) {
+ m_camera->markDirty();
+ }
+
+ m_systemView.draw(m_camera.get());
+ TimeMan::draw();
+ m_camera->draw();
+ m_systemView.drawOver(m_camera.get());
+ context.draw();
+ }
+
+ std::this_thread::sleep_until(end);
+ end = std::chrono::steady_clock::now();
+ auto diff = end - start;
+ m_delta = (double)(std::chrono::duration_cast<std::chrono::milliseconds>(diff).count()) / 1000.0;
+}
diff --git a/src/input.cpp b/src/input.cpp
new file mode 100644
index 0000000..5cbedb2
--- /dev/null
+++ b/src/input.cpp
@@ -0,0 +1,37 @@
+#include "input.hpp"
+namespace input {
+
+int getcode() {
+ int r = 0;
+ char c;
+ if(read(STDIN_FILENO, &c, 1) != 1) return -1;
+ if(c == '\x1b') {
+ char seq[3];
+ if(read(STDIN_FILENO, &seq[0], 1) != 1) return '\x1b';
+ if(read(STDIN_FILENO, &seq[1], 1) != 1) return '\x1b';
+ if(seq[0] == '[') {
+ if(seq[1] >= 0 && seq[1] <= '9') {
+ if(read(STDIN_FILENO, &seq[2], 1) != 1) return '\x1b';
+ if(seq[2] == '~') {
+ switch(seq[1]) {
+ case '1':
+ case '7': return CTRL_KEY_HOME;
+ case '4':
+ case '8': return CTRL_KEY_END;
+ default: return CTRL_RANGE_START + seq[1] + 20;
+ }
+ }
+ }else{
+ switch(seq[1]) {
+ default: return CTRL_RANGE_START + seq[1];
+ }
+ }
+ }else if(seq[0] == 'O') {
+ return CTRL_RANGE_START + seq[1];
+ }
+ return '\x1b';
+ }else{
+ return c;
+ }
+}
+}
diff --git a/src/keybind.cpp b/src/keybind.cpp
new file mode 100644
index 0000000..8283c4c
--- /dev/null
+++ b/src/keybind.cpp
@@ -0,0 +1,64 @@
+#include "keybind.hpp"
+#include "csv.hpp"
+#include "input.hpp"
+
+#include <algorithm>
+
+std::unordered_map<std::string, KeyMan::Bind> KeyMan::m_keybinds;
+std::unordered_map<std::string, std::string> KeyMan::m_keybindContexts;
+
+KeyMan::Binds KeyMan::binds;
+
+static std::unordered_map<int, std::string> CODENAMES =
+{
+ { input::CTRL_KEY_ARROWUP, "Up arrow" },
+ { input::CTRL_KEY_ARROWDOWN, "Down arrow" },
+ { input::CTRL_KEY_ARROWRIGHT, "Right arrow" },
+ { input::CTRL_KEY_ARROWLEFT, "Left arrow" }
+};
+
+void
+KeyMan::registerBind(int def,
+ const std::string &name,
+ const std::string &context,
+ const std::string &desc)
+{
+ auto find = m_keybinds.find(name);
+ if(find != m_keybinds.end()) {
+ find->second.ctx = context;
+ find->second.desc = desc;
+ }else{
+ Bind bind = { def, name, context, desc};
+ m_keybinds[name] = bind;
+ }
+ m_keybindContexts[name] = context;
+}
+
+void
+KeyMan::loadKeybindsFrom(const std::string &csvPath)
+{
+ csv::CSVFile<',', int, std::string> keybindData(csvPath);
+ for(auto &bind : keybindData.get()) {
+ int code = std::get<0>(bind);
+ std::string name = std::get<1>(bind);
+
+ m_keybinds[name] = { .code = code, .name = name, .ctx = "", .desc = ""};
+ }
+}
+
+void
+KeyMan::writeKeybindsTo(const std::string &csvPath)
+{
+ csv::CSVFile<',', int, std::string> keybindData(csvPath, true);
+ for(Bind &bind : KeyMan::binds()) {
+ keybindData.put({bind.code, bind.name});
+ }
+ keybindData.write();
+}
+
+std::string
+KeyMan::translateCode(int code)
+{
+ if(code < 256) return std::string(1, (char)code);
+ return CODENAMES[code];
+}
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..9ff09a6
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,26 @@
+#include <iostream>
+#include "game.hpp"
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+int
+main(int argc, char **argv)
+{
+ (void)argc;
+ (void)argv;
+
+ struct winsize w;
+ ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
+ fcntl(STDIN_FILENO, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);
+
+ Game::setup(w.ws_col, w.ws_row);
+
+ while(Game::running()) {
+ Game::turn();
+ }
+
+ Game::cleanup();
+ return 0;
+}
diff --git a/src/system.cpp b/src/system.cpp
new file mode 100644
index 0000000..974d0dc
--- /dev/null
+++ b/src/system.cpp
@@ -0,0 +1,517 @@
+#include "system.hpp"
+#include "timeman.hpp"
+#include "ecs.hpp"
+#include "vex.hpp"
+#include "units.hpp"
+#include "csv.hpp"
+#include "keybind.hpp"
+#include "game.hpp"
+#include <numbers>
+#include <string>
+
+static double G = 6.6743 * std::pow(10, -11);
+
+ecs::Entity &
+System::addOrbital(const std::string &name,
+ const std::string &orbitingName,
+ unsigned long a,
+ double e,
+ unit::Mass m,
+ unsigned r,
+ double M,
+ double w)
+{
+ M *= (std::numbers::pi / 180.0);
+ w *= (std::numbers::pi / 180.0);
+
+ SystemTreeNode *treeNode = getNode(orbitingName);
+ ecs::Entity &newOrbital = m_entityMan.newEntity()
+ .addComponent(ecs::PositionComponent{vex::vec2<long>{0, 0}})
+ .addComponent(ecs::MassComponent{m})
+ .addComponent(ecs::OrbitalComponent{.origin = treeNode->entityId, .a = (long)a, .e = e, .w = w, .M = M, .T = 0, .v = 0})
+ .addComponent(ecs::RenderCircleComponent{r})
+ .addComponent(ecs::NameComponent{name});
+ treeNode->children.push_back({newOrbital.id, {}});
+ return newOrbital;
+}
+
+System::System()
+{
+ auto sol = m_entityMan.newEntity()
+ .addComponent(ecs::PositionComponent{vex::vec2<long>{0, 0}})
+ .addComponent(ecs::MassComponent{unit::solMass})
+ .addComponent(ecs::RenderCircleComponent{695700})
+ .addComponent(ecs::NameComponent{"Sol"});
+ m_systemTree.entityId = sol.id;
+
+ csv::CSVFile<',', std::string, std::string, double, double, double, double, double, double> planetData("data/sol_planets.csv");
+ for(auto &planet : planetData.get()) {
+ std::string name = std::get<0>(planet);
+ std::string orbiting = std::get<1>(planet);
+ double sma = std::get<2>(planet) * unit::AU;
+ double e = std::get<3>(planet);
+ unit::Mass m = unit::earthMass * std::get<4>(planet);
+ double r = std::get<5>(planet) * unit::earthRad;
+ double M = std::get<6>(planet);
+ double w = std::get<7>(planet);
+ addOrbital(name, orbiting, sma, e, m, r, M, w);
+ }
+
+ csv::CSVFile<',', std::string, std::string, double, double, double, double, double, double> satelliteData("data/sol_satellites.csv");
+ for(auto &satellite : satelliteData.get()) {
+ std::string name = std::get<0>(satellite);
+ std::string orbiting = std::get<1>(satellite);
+ double sma = std::get<2>(satellite) * unit::AU;
+ double e = std::get<3>(satellite);
+ unit::Mass m = unit::earthMass * std::get<4>(satellite);
+ double r = std::get<5>(satellite) * unit::earthRad;
+ double M = std::get<6>(satellite);
+ double w = std::get<7>(satellite);
+ addOrbital(name, orbiting, sma, e, m, r, M, w);
+ }
+
+ csv::CSVFile<',', std::string, double, double, double, double, double, std::string> asteroidData("data/sol_asteroids.csv");
+ for(auto &asteroid : asteroidData.get()) {
+ std::string name = std::get<0>(asteroid);
+ if(name == "Missing") name = std::get<6>(asteroid);
+ addOrbital(name,
+ "Sol",
+ (unsigned long)(std::get<1>(asteroid) * unit::AU),
+ std::get<2>(asteroid),
+ unit::Mass(0),
+ (unsigned)std::get<3>(asteroid),
+ std::get<4>(asteroid),
+ std::get<5>(asteroid));
+ }
+}
+
+constexpr static double tau = std::numbers::pi * 2;
+
+void
+System::tickOrbitals(unit::Time time)
+{
+ for(ecs::Entity &e : m_entityMan.getWith<ecs::OrbitalComponent>()) {
+ auto &oc = e.get<ecs::OrbitalComponent>();
+ auto &pc = e.get<ecs::PositionComponent>();
+ auto &mc = e.get<ecs::MassComponent>();
+
+ ecs::Entity &o = m_entityMan[oc.origin];
+ auto &opc = o.get<ecs::PositionComponent>();
+ auto &om = o.get<ecs::MassComponent>();
+
+ double e2 = oc.e * oc.e;
+ double td = (double)time();
+ if(oc.T == 0) {
+ double u = G * (om.mass() + mc.mass());
+ double am = (double)oc.a * 1000.0;
+ oc.T = tau * std::sqrt((am * am * am) / u);
+ }
+ double n = tau / oc.T;
+ double M = oc.M + (n * td);
+ double E = M;
+
+ int its = 0;
+ while(true) {
+ double dE = (E - oc.e * std::sin(E) - M) / (1 - oc.e * std::cos(E));
+ E -= dE;
+ its++;
+ if(std::abs(dE) < 1e-6) break;
+ }
+
+ double x = std::cos(E) - oc.e;
+ double y = std::sin(E) * std::sqrt(1 - e2);
+
+ double v = std::atan2(y, x) + oc.w;
+ oc.v = v;
+
+ double r = std::sqrt(x*x + y*y) * (double)oc.a;
+
+ vex::vec2<double> polar(r, v);
+ pc.position = vex::cartesian<long>(polar) + opc.position;
+ }
+
+}
+
+void
+System::update()
+{
+ tickOrbitals(TimeMan::time());
+}
+
+ecs::Entity &
+System::getBody(std::size_t id) {
+ return m_entityMan[id];
+}
+
+System::SystemTreeNode *
+System::traverseSystemTree(SystemTreeNode &node, const std::string &name)
+{
+ SystemTreeNode *found = nullptr;
+ ecs::Entity &entity = getBody(node.entityId);
+ auto &namecomp = entity.get<ecs::NameComponent>();
+ if(namecomp.name == name) found = &node;
+
+ for(SystemTreeNode &child : node.children) {
+ if(found != nullptr) break;
+ found = traverseSystemTree(child, name);
+ }
+ return found;
+}
+
+System::SystemTreeNode *
+System::getNode(const std::string &name)
+{
+ SystemTreeNode *treeRes = traverseSystemTree(m_systemTree, name);
+ if(treeRes == nullptr)
+ treeRes = &m_systemTree;
+ return treeRes;
+}
+
+void
+SystemView::view(System *system)
+{
+ m_system = system;
+ m_focus = &system->m_systemTree;
+}
+
+void
+SystemView::keypress(Camera *camera, int key)
+{
+ WindowContext &context = Game::contexts();
+ if(context.getFocusedString() == WINDOW_SYSTEMVIEW_SEARCH_ID) {
+ m_focusSearch->keypress(key);
+ if(!Game::paused()) {
+ Search *fp = m_focusSearch.release();
+ delete fp;
+ }
+ }
+ if(context.getFocusedString() != WINDOW_SYSTEMVIEW_ID) return;
+ if(key == KeyMan::binds[BIND_SYSTEMVIEW_PANUP].code) camera->move(0, camera->getscale());
+ if(key == KeyMan::binds[BIND_SYSTEMVIEW_PANDOWN].code) camera->move(0, -(long)camera->getscale());
+ if(key == KeyMan::binds[BIND_SYSTEMVIEW_PANRIGHT].code) camera->move(camera->getscale(), 0);
+ if(key == KeyMan::binds[BIND_SYSTEMVIEW_PANLEFT].code) camera->move(-(long)camera->getscale(), 0);
+ if(key == KeyMan::binds[BIND_SYSTEMVIEW_INCSCALE].code) camera->setscale(camera->getscale() * 2);
+ if(key == KeyMan::binds[BIND_SYSTEMVIEW_DECSCALE].code) camera->setscale(camera->getscale() / 2);
+ if(key == KeyMan::binds[BIND_SYSTEMVIEW_SEARCH].code) {
+ Game::setState(Game::State::PAUSED_INPUT);
+ context.focus(WINDOW_SYSTEMVIEW_SEARCH_ID);
+ context.setWindowHidden(WINDOW_SYSTEMVIEW_SEARCH_ID, false);
+ m_focusSearch = std::make_unique<Search>(this);
+ }
+}
+
+void
+SystemView::update(Camera *camera)
+{
+ if(Game::paused()) return;
+ auto &efoc = m_system->m_entityMan[m_focus->entityId];
+ auto &efocp = efoc.get<ecs::PositionComponent>();
+ if(efocp.position != camera->getorigin()) {
+ camera->setorigin(efocp.position);
+ }
+}
+
+void
+SystemView::drawOver(Camera *camera) {
+ auto &efoc = m_system->m_entityMan[m_focus->entityId];
+ auto &efocp = efoc.get<ecs::PositionComponent>();
+ auto &efocm = efoc.get<ecs::MassComponent>();
+
+ WindowContext &context = Game::contexts();
+ Window &infoWindow = context[WINDOW_BODYINFO_ID];
+ Window &viewWindow = context[WINDOW_SYSTEMVIEW_ID];
+
+ infoWindow << straw::clear(' ');
+ infoWindow << straw::move(0, 0) << "Focus: " << efoc.get<ecs::NameComponent>().name << '\n';
+ if(efoc.contains<ecs::OrbitalComponent>()) {
+ auto &efoco = efoc.get<ecs::OrbitalComponent>();
+ ecs::Entity &efoc_origin = m_system->m_entityMan[efoco.origin];
+
+ infoWindow << "Orbiting: " << efoc_origin.get<ecs::NameComponent>().name << '\n';
+ infoWindow << "Distance: " << std::abs((double)(efocp.position - efoc_origin.get<ecs::PositionComponent>().position).magnitude()) << "km\n";
+ infoWindow << "Period: " << efoco.T / unit::DAY_SECONDS << " days\n";
+ infoWindow << "Angle: " << efoco.v * (180.0 / std::numbers::pi) << '\n';
+ infoWindow << "Eccentricity: " << efoco.e << '\n';
+ infoWindow << "Mass: " << efocm.mass() << '\n';
+ }
+ vex::vec2<unsigned> viewdims(
+ viewWindow.screen()->getwidth(),
+ viewWindow.screen()->getheight());
+
+ viewWindow << straw::move(0, 0) <<
+ straw::setcolor(straw::WHITE, straw::BLACK) <<
+ "Press '" <<
+ KeyMan::translateCode(KeyMan::binds[BIND_SYSTEMVIEW_SEARCH].code) <<
+ "' to change focus";
+
+ double scale = camera->getscale() * (viewdims[0] / 2.0);
+ if(scale > 1e7) {
+ viewWindow << straw::move(0, viewdims[1] - 1) << scale / unit::AU << " AU";
+ }else{
+ viewWindow << straw::move(0, viewdims[1] - 1) << scale << " km";
+ }
+
+}
+
+void
+SystemView::draw(Camera *camera)
+{
+ if(m_focusSearch != nullptr) m_focusSearch->draw();
+ if(!camera->dirty()) return;
+ auto &efoc = m_system->m_entityMan[m_focus->entityId];
+ auto &efocp = efoc.get<ecs::PositionComponent>();
+ auto &efocm = efoc.get<ecs::MassComponent>();
+
+ if(efoc.contains<ecs::OrbitalComponent>()) {
+ auto &oc = efoc.get<ecs::OrbitalComponent>();
+ auto &om = efoc.get<ecs::MassComponent>();
+ ecs::Entity &origin = m_system->m_entityMan[oc.origin];
+ auto pc = origin.get<ecs::PositionComponent>();
+
+ std::vector<vex::vec2<long>> points;
+ float i = 0.0;
+ while(i < tau){
+ double e2 = oc.e * oc.e;
+ double M = oc.M + i;
+ double E = M;
+
+ int its = 0;
+ while(its < 512) {
+ double dE = (E - oc.e * std::sin(E) - M) / (1 - oc.e * std::cos(E));
+ E -= dE;
+ its++;
+ if(std::abs(dE) < 1e-6) break;
+ }
+
+ double x = (std::cos(E) - oc.e);
+ double y = (std::sin(E) * std::sqrt(1 - e2));
+
+ double v = std::atan2(y, x) + oc.w;
+ double r = std::sqrt(x*x + y*y) * (double)oc.a;
+
+
+ vex::vec2<double> polar{r, v};
+ vex::vec2<long> cart = vex::cartesian<long>(polar) + pc.position;
+
+ points.push_back(cart);
+ i += 0.01;
+ }
+ for(unsigned i = 0; i < points.size(); i++) {
+ if(i == 0) {
+ camera->batchShape(shapes::line<long>(points[points.size() - 1], points[i]), straw::color(0, 0, 255), '#');
+ }else{
+ camera->batchShape(shapes::line<long>(points[i-1], points[i]), straw::color(0, 0, 255), '#');
+ }
+ }
+ }
+
+ for(ecs::Entity &e : m_system->m_entityMan.getWith<ecs::RenderCircleComponent>()) {
+ auto &pc = e.get<ecs::PositionComponent>();
+ auto &cc = e.get<ecs::RenderCircleComponent>();
+ unsigned id = e.id;
+
+ long cr = cc.radius;
+ if(cr < camera->getscale()) cr = camera->getscale();
+ shapes::ellipse<long> circle(pc.position, cr, cr);
+
+ straw::color color = id == m_focus->entityId ? straw::color{255, 255, 0} : straw::WHITE;
+ if(cc.radius < cr) {
+ camera->batchShape(circle, color, '*');
+ }else{
+ camera->batchShape(circle, color, '#');
+ }
+ }
+}
+
+ecs::Entity &
+SystemView::getBody(int id) const
+{
+ return m_system->m_entityMan[id];
+}
+
+int
+SystemView::getBodyIdByName(const std::string &name)
+{
+ for(ecs::Entity &entity : m_system->m_entityMan.all()) {
+ int id = entity.id;
+ if(entity.contains<ecs::NameComponent>()) {
+ auto &namecomp = entity.get<ecs::NameComponent>();
+ if(namecomp.name == name) return id;
+ }
+ }
+ return -1;
+}
+
+void
+SystemView::Search::addNodeToTree(SystemTreeDisplayNode &root, System::SystemTreeNode *node)
+{
+ m_displayTreeFlat.emplace_back(&root);
+ for(auto &child : node->children)
+ {
+ ecs::NameComponent &namecomp = m_systemView->m_system->m_entityMan[child.entityId].get<ecs::NameComponent>();
+ root.children.push_back(
+ {&child,
+ {},
+ &root,
+ (unsigned)m_displayTreeFlat.size(),
+ m_query.empty(),
+ m_query.empty() ? false : namecomp.name.find(m_query) == std::string::npos});
+ addNodeToTree(root.children.back(), &child);
+ }
+}
+
+void
+SystemView::Search::rebuild()
+{
+ System::SystemTreeNode *systemRoot = &m_systemView->m_system->m_systemTree;
+ m_displayTree = {systemRoot, {}, nullptr, 0, false, false};
+ m_displayTreeFlat.clear();
+ m_selectionIndex = 0;
+
+ addNodeToTree(m_displayTree, systemRoot);
+ for(unsigned i = 0; auto *node : m_displayTreeFlat) {
+ if(m_systemView->m_focus == node->node) {
+ m_selectionIndex = i;
+ break;
+ }
+ i++;
+ }
+ SystemTreeDisplayNode *recurse = m_displayTreeFlat[m_selectionIndex];
+ while(recurse->parent != nullptr) {
+ recurse->parent->collapsed = false;
+ recurse->parent->hidden = false;
+ recurse = recurse->parent;
+ }
+}
+
+void
+SystemView::Search::drawNode(
+ SystemTreeDisplayNode &root,
+ Window &searchWindow,
+ unsigned indent)
+{
+ unsigned windowH = searchWindow.screen()->getheight();
+ unsigned cursorY = searchWindow.screen()->getcursory();
+ if(cursorY == windowH && root.index > m_selectionIndex) return;
+
+ ecs::NameComponent &namecomp = m_systemView->m_system->m_entityMan[root.node->entityId].get<ecs::NameComponent>();
+
+ if(root.index == m_selectionIndex) {
+ searchWindow << straw::setcolor(straw::BLACK, straw::WHITE);
+ }else searchWindow << straw::setcolor(straw::WHITE, straw::BLACK);
+
+
+ if(!root.hidden) {
+ if(m_query.empty()) searchWindow << std::string((indent * 4), ' ');
+ if(root.children.size() > 0)
+ searchWindow << '[' << (root.collapsed ? '+' : '-') << "] ";
+ searchWindow << namecomp.name << straw::setcolor(straw::WHITE, straw::BLACK) << '\n';
+ }
+
+ if(!root.collapsed) {
+ for(auto &child : root.children) drawNode(child, searchWindow, indent + 1);
+ }
+}
+
+SystemView::Search::Search(SystemView *systemView) :
+ m_systemView(systemView), m_selectionIndex(0), m_dirty(true)
+{
+ rebuild();
+}
+
+void
+SystemView::Search::finish()
+{
+ WindowContext &context = Game::contexts();
+ Game::setState(Game::State::RUNNING);
+ context.setWindowHidden(WINDOW_SYSTEMVIEW_SEARCH_ID, true);
+ context.focus(WINDOW_SYSTEMVIEW_ID);
+}
+
+void
+SystemView::Search::keypress(int key)
+{
+ if(key == KeyMan::binds[BIND_G_ESCAPE].code) {
+ finish();
+ }else
+ if(key == KeyMan::binds[BIND_SYSTEMVIEW_SEARCH_NEXT].code) {
+ if(m_selectionIndex == m_displayTreeFlat.size() - 1) return;
+ for(m_selectionIndex++; m_selectionIndex < m_displayTreeFlat.size() - 1; ++m_selectionIndex) {
+ if(!m_displayTreeFlat[m_selectionIndex]->hidden) break;
+ }
+ if(m_displayTreeFlat[m_selectionIndex]->hidden) m_selectionIndex = 0;
+ SystemTreeDisplayNode *node = m_displayTreeFlat[m_selectionIndex];
+ while(node->parent != nullptr) {
+ if(!node->parent->collapsed) break;
+ m_selectionIndex += node->parent->children.size();
+ node = node->parent;
+ }
+
+ m_dirty = true;
+ }else
+ if(key == KeyMan::binds[BIND_SYSTEMVIEW_SEARCH_PREV].code) {
+ if(m_selectionIndex == 0) return;
+ for(m_selectionIndex--; m_selectionIndex > 0; --m_selectionIndex) {
+ if(!m_displayTreeFlat[m_selectionIndex]->hidden) break;
+ }
+ SystemTreeDisplayNode *node = m_displayTreeFlat[m_selectionIndex];
+ while(node->parent != nullptr) {
+ if(!node->parent->collapsed) break;
+ m_selectionIndex -= node->parent->children.size();
+ node = node->parent;
+ }
+
+ m_dirty = true;
+ }else
+ if(key == KeyMan::binds[BIND_SYSTEMVIEW_SEARCH_TOP].code) {
+ m_selectionIndex = 0;
+ for(; m_selectionIndex < m_displayTreeFlat.size(); ++m_selectionIndex) {
+ if(!m_displayTreeFlat[m_selectionIndex]->hidden) break;
+ }
+ m_dirty = true;
+ }else
+ if(key == KeyMan::binds[BIND_SYSTEMVIEW_SEARCH_BOTTOM].code) {
+ m_selectionIndex = m_displayTreeFlat.size() - 1;
+ for(; m_selectionIndex > 0; --m_selectionIndex) {
+ if(!m_displayTreeFlat[m_selectionIndex]->hidden) break;
+ }
+ m_dirty = true;
+ }else
+ if(key == KeyMan::binds[BIND_SYSTEMVIEW_SEARCH_COLLAPSE].code) {
+ m_displayTreeFlat[m_selectionIndex]->collapsed = !m_displayTreeFlat[m_selectionIndex]->collapsed;
+ m_dirty = true;
+ }else
+ if(key == KeyMan::binds[BIND_G_SELECT].code) {
+ m_systemView->m_focus = m_displayTreeFlat[m_selectionIndex]->node;
+ finish();
+ }else
+ {
+ if(key < 0) return;
+ switch(key) {
+ case 127:
+ case '\b': {
+ if(!m_query.empty()) m_query.pop_back();
+ } break;
+ default: m_query.push_back((char)key); break;
+ }
+ rebuild();
+ m_dirty = true;
+ }
+}
+
+void
+SystemView::Search::draw()
+{
+ if(!m_dirty) return;
+
+ WindowContext &windowContext = Game::contexts();
+ Window &searchWindow = windowContext[WINDOW_SYSTEMVIEW_SEARCH_ID];
+
+ searchWindow << straw::clear(' ') << straw::move(0, 0);
+ searchWindow << "Query: " << m_query << '\n';
+
+ drawNode(m_displayTree, searchWindow, 0);
+
+ searchWindow << straw::flush();
+ m_dirty = false;
+}
diff --git a/src/timeman.cpp b/src/timeman.cpp
new file mode 100644
index 0000000..f043894
--- /dev/null
+++ b/src/timeman.cpp
@@ -0,0 +1,49 @@
+#include "timeman.hpp"
+#include "keybind.hpp"
+#include "window.hpp"
+#include "game.hpp"
+
+unit::Time TimeMan::m_time(0);
+unit::Time TimeMan::m_step(unit::DAY_SECONDS);
+bool TimeMan::m_auto;
+bool TimeMan::m_changed;
+
+void
+TimeMan::init()
+{
+ KeyMan::registerBind('.', BIND_TIMEMAN_STEP, CTX_TIMEMAN, "Move time ahead by a step");
+ KeyMan::registerBind('+', BIND_TIMEMAN_INCSTEP, CTX_TIMEMAN, "Increase the timestep");
+ KeyMan::registerBind('-', BIND_TIMEMAN_DECSTEP, CTX_TIMEMAN, "Decrease the timestep");
+ KeyMan::registerBind('a', BIND_TIMEMAN_TOGGLEAUTO, CTX_TIMEMAN, "Toggle if time will move automatically");
+ m_changed = true;
+}
+
+void
+TimeMan::update(int c)
+{
+ WindowContext &context = Game::contexts();
+ m_changed = false;
+ if(!Game::paused()) {
+ if(m_auto) {
+ m_time += (m_step);
+ m_changed = true;
+ }
+ }
+ if(context.getFocusedString() != WINDOW_TIMEMAN_ID) return;
+ if(c == KeyMan::binds[BIND_TIMEMAN_INCSTEP].code) m_step = unit::Time(std::max<long>(1, m_step() * 2));
+ if(c == KeyMan::binds[BIND_TIMEMAN_DECSTEP].code) m_step = unit::Time(std::max<long>(1, m_step() / 2));
+ if(c == KeyMan::binds[BIND_TIMEMAN_TOGGLEAUTO].code) m_auto = !m_auto;
+ if(c == KeyMan::binds[BIND_TIMEMAN_STEP].code && !Game::paused()) { m_time += m_step; m_changed = true; }
+}
+
+void
+TimeMan::draw()
+{
+ WindowContext &context = Game::contexts();
+ Window &timeWindow = context[WINDOW_TIMEMAN_ID];
+ timeWindow << straw::clear(' ');
+
+ timeWindow << straw::move(0, 0) << straw::resetcolor() << m_time.format("%S %D, %C \n%H:%m\n\n");
+ timeWindow << m_step.format("Step:\n%Y Years, %M Months\n%D Days, %H Hours\n%m Minutes, %s Seconds\n\n");
+ if(m_auto) timeWindow << "Auto";
+}
diff --git a/src/units.cpp b/src/units.cpp
new file mode 100644
index 0000000..7cc7d61
--- /dev/null
+++ b/src/units.cpp
@@ -0,0 +1,61 @@
+#include "units.hpp"
+#include <sstream>
+#include <cstring>
+#include <iostream>
+
+namespace unit {
+
+std::string
+Time::format(const char *fmt)
+{
+ std::stringstream ss;
+ for(; *fmt; fmt++) {
+ if(*fmt != '%') {
+ ss << *fmt;
+ continue;
+ }
+ fmt++;
+ switch(*fmt) {
+ case '%':
+ ss << '%';
+ break;
+ case 'Y':
+ ss << real_years();
+ break;
+ case 'C':
+ ss << years();
+ break;
+ case 'S': {
+ Time year = current_year();
+ ss << month_str[year.months()];
+ break; }
+ case 'M': {
+ Time year = current_year();
+ ss << year.months();
+ break; }
+ case 'W': {
+ Time month = current_month();
+ ss << month.weeks();
+ break; }
+ case 'D': {
+ Time month = current_month();
+ ss << month.days();
+ break; }
+ case 'H': {
+ Time day = current_day();
+ ss << day.hours();
+ break; }
+ case 'm': {
+ Time hour = current_hour();
+ ss << hour.minutes();
+ break; }
+ case 's': {
+ Time minute = current_minute();
+ ss << minute.seconds();
+ break; }
+ }
+ }
+ return ss.str();
+}
+
+}
diff --git a/src/window.cpp b/src/window.cpp
new file mode 100644
index 0000000..4e487f3
--- /dev/null
+++ b/src/window.cpp
@@ -0,0 +1,72 @@
+#include "window.hpp"
+#include "keybind.hpp"
+
+void
+Window::draw(bool focus)
+{
+ if(m_hidden) return;
+ if(focus) {
+ m_border << straw::setcolor(straw::BLACK, straw::WHITE) << straw::clear(' ') << straw::move(0, 0) << m_title << straw::resetcolor();
+ }else{
+ m_border << straw::setcolor(straw::WHITE, straw::BLACK) << straw::clear(' ') << straw::move(0, 0) << m_title;
+ }
+ m_border.flush();
+ m_screen.flush();
+}
+
+void
+WindowContext::registerWindow(const std::string &id,
+ const std::string &title,
+ unsigned x, unsigned y,
+ unsigned w, unsigned h,
+ bool hidden)
+{
+ m_windows.emplace(id, Window(title, x, y, w, h, hidden));
+ m_windowOrder.push_back(id);
+}
+
+void
+WindowContext::update(int code)
+{
+ if(code == KeyMan::binds[BIND_G_NEXTWIN].code) {
+ m_focus = (m_focus + 1) % m_windows.size();
+ while(m_windows.at(m_windowOrder[m_focus]).hidden()) {
+ m_focus = (m_focus + 1) % m_windows.size();
+ }
+ }
+ if(code == KeyMan::binds[BIND_G_PREVWIN].code) {
+ m_focus = (m_focus == 0 ? m_windows.size() - 1 : m_focus - 1);
+ while(m_windows.at(m_windowOrder[m_focus]).hidden()) {
+ m_focus = (m_focus == 0 ? m_windows.size() - 1 : m_focus - 1);
+ }
+ }
+}
+
+void
+WindowContext::draw()
+{
+ for(unsigned i = 0; i < m_windows.size(); i++) {
+ m_windows.at(m_windowOrder[i]).draw(i == m_focus);
+ }
+}
+
+void
+WindowContext::focus(const std::string &id)
+{
+ for(unsigned i = 0; i < m_windowOrder.size(); i++) {
+ if(m_windowOrder[i] == id) {
+ m_focus = i;
+ return;
+ }
+ }
+}
+
+void
+WindowContext::setWindowHidden(const std::string &id, bool mode)
+{
+ m_windows.at(id).setHidden(mode);
+ for(unsigned i = 0; i < m_windows.size(); i++) {
+ if(m_windowOrder[i] == id && mode) continue;
+ m_windows.at(m_windowOrder[i]) << straw::redraw();
+ }
+}