Giter Club home page Giter Club logo

ogn-live's Introduction

ogn-live

Talking about http://live.glidernet.org

This website displays live (mostly) glider traffic. More information can be found on: http://glidernet.org

You can use this repo to report issues.

Usage

You can create custom links to ogn-live, for example:

http://live.glidernet.org/#c=44.84593,5.83412&z=6&o=1&b=46.3069,42.5792,11.0471,0.5003&l=pr&w=0&p=2&t=http://cunimb.fr/tasks_example.txt

URL Parameters

The following URL parameters are currently supported:

Flag Description Value
c center coordinates latitude,longitude
w show warning window 0 - hidden
z zoom level 0 (entire world) to 21 (most detailed)
o show offline aircrafts 1 - show offline
m map type s:sattelite, h:hybrid, r:roadmap, t:relief
b bounds lat_max,lat_min,lon_max,lon_min
s auto set to map 1 - true
l show special layers v:wind, p:pressure, z:airspaces, a:airports, r:receivers
u use imperial units i - activated
p path length default: 5 min, p=2: 10 min, p=3 all points
n show side panel 0 - hidden
t load task file, (see Tasks) URL

source

Task File Format

Currently the code handles JSON and XCSoar TSK files. You can generate such a task file with many programs (e.g. prosoar.de). The task file can be local or hosted somewhere (hosting with CORS). Remark: github and gists has CORS enabled.

To display only aircrafts you want, you can specify a "whitelist" of device IDs in the task file (currently only supported by JSON files). The devices need to be registered in the OGN database to be recognized.

Example task file (json-encoded)

{"tasks": [
    {"name": "15m", "color": "0000FF", "legs": [ [47.3,1.55],["L",3000],[48.2,2.3],["C",30000],[47.5,-1.3],["C",50000],[47.3,1.5],["L",1000] ] },
    {"name": "standard","color": "00FF00","legs": [ [47.2,1.55],["Q180",3000],[46.5,2.3],["Q",10000],[46.5,-0.2],["Q",10000],[47,-0.2],["Q",10000],[47.2,1.5],["Q180",3000] ] },
    {"name": "open","color": "000000","legs": [ [47.25,1.6],["L",3000],[48,3],["C",500],[46,3],["C",500],[47.22,1.6],["L",1000] ],"wlist": ["DD1111", "DD2222", "DD3333", "DD4444"]}
]}

There is an external program cup2ogn.exe that will generate such a file either of a .CUC (SeeYou competition scoring file), or of a .CUP file (with or without a task, but with is better).

Backend

The backend code used in production is not yet public. However there is a alternative backend ogn-live-backend.

AJAX endpoints

Description name URL
Receiver list rxml rec.php
Flights cxml lxml.php?a={{ all }}{{ boundc }}{{ recc }}{{ parc }}{{ tz }}{{ hashy }}
Flight path cxml1 livexml1.php?id={{ p }}&l={{ lo }}
Flight data dxml dataxml.php?i=M_{{ p }}&f={{ fi }}
Variable Description Value
all show offline gliders 1 - true, 0 -false
boundc Bounds &b={{ amax }}&c={{ amin }}&d={{ omax }}&e={{ omin }}
amax Latitude eg. 50.123456789
omax Longitude eg. -9.123456789
recc unknown &r={{ rec }}
parc unknown &p={{ pw }}
tz timezone offset eg. -120
hashy &y={{ dt }}, "" for all types
dt device type bitmask 0x1 ICAO, 0x2 Flarm, 0x4 OGN
p flight identifier eg. 12345678
lo longitude.toFixed() eg. 7
fi flight id {{ reg }} or 'hidden'
reg registry eg. XXXXXX
encpath encoded path

Examples:

http://live.glidernet.org/rec.php

<?xml version="1.0" encoding="UTF-8"?>
<markers>
<m e="0"/>
<m a="EHTL" b="52.0607986" c="5.9376998" d="1"/>
<m a="Musbach" b="48.5047989" c="8.4768000" d="1"/>
</markers>

http://live.glidernet.org/lxml.php?a=0&b=48.86612088725434&c=48.84692039542289&d=2.413544128417925&e=2.3053974609374563&z=2 http://live.glidernet.org/lxml.php?a=1&b=51.7568&c=47.3490&d=15.0239&e=1.0054&z=2

<?xml version="1.0" encoding="UTF-8"?>
<markers>
<m a="48.660000,12.198000,_b8,8bde76b8,807,23:11:22,633,103,131,-0.4,3,Moosburg,0,8bde76b8"/>
<m a="49.000500,9.080170,BF,D-9989,284,21:51:28,5427,0,0,-0.1,1,Loechgau,DDA286,fc73a533"/>
</markers>

http://live.glidernet.org/livexml1.php?id=87183180&l=7

<?xml version="1.0" encoding="UTF-8"?>
<markers>
<m e="0" i="{{ p }}" r="{{ enc_path }}"/>
</markers>```

http://live.glidernet.org/dataxml.php?i=M_4c4d735b&f=DDE1E1
```

License

Licensed under the AGPLv3.

ogn-live's People

Contributors

clementallen avatar cunimb avatar dbursem avatar kerel-fs avatar nbonniere avatar snip avatar turbo87 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ogn-live's Issues

Question about the livexml1.php endpoint

There is no documentation as to how the encoded path should be decoded for use. How would I go about this?

Example response from url https://live.glidernet.org/livexml1.php?id=1f6e1bd2:

<?xml version="1.0" encoding="UTF-8"?>
<markers>
<m e="0" i="1f6e1bd2" r="odq{HpmiB???C?BC?B??B?>??C>a@p@m@bAaAzAuCjE_AbByD`Fg@b@e@^i@\g@Zk@RsA\sD\m@?u@@_EKq@@cBDaEd@q@Nq@Lq@Bq@??Bq@?CCm@C??u@CcBIqEGq@@?@q@Hm@L_B\o@L?@i@Pq@NyAb@k@P?@k@R?Cm@V?Cg@ReCt@g@N?B}Bl@?@kHfBqErAsA\g@NA?sAd@c@R??a@ZY\Sj@Ct@H\|@`@t@b@l@p@d@t@VbCD~@U`C{A?BzBcCfEyIzAsD\|AqDl@{Aj@{Al@_B?@n@{Ah@aBfD{J?>@?j@wA`CiG?Cj@sAh@_B~BuGpAuDvA}DtAwD?Bl@wAjCqFx@_AhDkCv@a@v@SpBWbDO@@nEZ?C?BxA\pAf@lAl@b@^\|A\|A\`@v@`A`@`@X^Xd@nAbBt@bAX`@z@dA`BbB\`@xBtCz@nA?@`@f@`ArAfBvB`@f@\j@^f@`@l@pCfEB?lBrCp@nA~@zBDh@Db@?@E`@B?I`@QXSLUD[C]C?CyAiAYe@]u@u@sBU}@C?W}@oAwDB?C?O_AC?kA}Dw@yBC?Y_AC?]{@_AsBYq@w@gB?A]m@[m@{@yAB?C?w@wAC?aAoA?Aa@c@{EiEc@]C@c@YiAg@aAWa@AsDl@?Bw@j@YR?BcAdAyAtB?CK\a@t@u@dA??_@t@?AMd@?A?@?A?@Cf@Aj@@?A?@?Bj@?BLj@Tl@?BlBfB?B`B`@?AzC`@bBPpHv@bBR`BPp@LjCl@f@NpAf@lAj@f@VhDbB?AvEbCrAx@?@fAdA`@d@vBzAj@ZC?f@`@`@`@?@^`@Rl@Ll@Bl@?j@Mf@?COZ[L]D]IB?C?aAk@_AmA_@u@y@gCYgAYkAuBkG]s@_@o@y@gBA?{@qAa@_@]a@a@M]AYHO\G\?b@F`@Jd@?C?B?CdAhB\`@bAbAb@\nA~@j@b@f@Zf@`@h@^f@d@`@^?A?@B?C?f@b@\|BtC?@d@b@?AzAxBvAfCC?Rp@Lv@?l@Gl@If@O`@C??CSVA?WD]C?B{@a@C??>eBkBa@s@sBwF]aAu@kCu@kC?A?@UgAcDcOeAuEu@uBBC]o@]g@oAyAYS]C?C@?]CUB?BSHSPMT?BC\?`@?fAFf@Hf@^lAB?C?Vd@z@fA\d@b@`@d@`@\|DdDrBfBB@b@\jAfAhAhAB?b@d@?C?BdAfA?@?Af@d@lBlB\f@`@d@v@rAVj@r@nCB?Nl@Pr@C?Rt@Nv@Rz@Pz@^xBPz@@?A?b@nBB?C?Nt@?Bd@nDv@fHH~@XrBLz@`@nBXpBLz@^xD\\|B`@bCR~@N~@R~@j@xB`ArDj@vBVx@Tx@j@tB?AV\|@Tz@P\|@T~@n@zBT\|@Z~@T`At@~B\z@\x@p@~BxAvFR\|@C?Vx@f@vBVz@Rx@h@nB?BPt@Tx@Rr@j@jB~@hDf@vB?B@?A?h@\|BVx@R~@pBzHRbAX`AV\|@p@fCT`ApBfIC?z@zDd@xBb@vB`@xBR~@R\|@f@~Bz@\|DNz@X\|@R~@?CRz@Lv@R\|@N~@z@vDV~@j@\|BC?VbAT\|@V~@R~@l@\|BV`A?A?@?ARx@?@Rz@f@zBNx@Lt@R~@Lz@Jz@Px@C?\vBL~@z@tHTnBLv@Dr@B?RvBB?Dz@L~@^`EL~@R`C?BHt@Hv@Lp@Hp@Jj@Fl@Hp@J\|AA?RjCH`BC?Dp@A?Dt@Dp@Ft@Hz@C?Hz@b@vBB?Rz@Vt@?>??h@hBj@\|AVn@nBjDd@b@nAz@xAj@b@VtAf@xA^p@LjEHz@CpBMv@Mz@KlDe@z@IrBWz@IjMiBpBa@z@O@?tBe@z@UtDyA~@a@v@a@~@[nDeAx@UdDcApBg@nBk@x@Mr@Mp@CB?t@Av@EzBQC?z@E~@A?AnBTj@`@B?b@b@Xj@B?C?Ll@?@?f@E`@QPUHWEWWA?sAcBB?_AyA_AaB]o@}@}AaBkC]e@eA_A}@Y{@Oy@>SFUHg@^y@\|@c@l@?BiA\|A}@v@{@hASXy@nAm@j@WRcBn@YHYHo@VeA`@aAf@WHUHWHm@VWLk@RmBlA{@\|@yArAqAXe@AeBIkBWaAOa@M]S]O_@I]Q_ASw@?C?YB[DwBB}@C]Cy@Cw@HWPO\Ed@?j@Dl@?ARp@rBfBxCl@rB?\|Dc@bGmA`C{@fEgB`CoAdCmAdAc@dCeA\|@a@~@WdC{@C?\|BiAB@zBoAz@e@~DoB`GeC@?`C_AjE_BdA[B?\|@m@A?fCmAC?hCgA?>fC}A?ClI}EfCmA\|BmAhI_D`EoA`AUfEgArMkD\|@]rFkBvBm@lD}@nDg@z@Az@?vBDhDXlBPhB\t@PfBh@C?\|Ax@?@p@\f@d@?C`CzBfCtBB?`CbCb@p@bB`D\t@dC`EfAnAvBlBj@`@nAfAtAhAf@j@n@b@f@d@dFxDC?l@`@j@f@f@l@\n@C?Vt@Hz@Cn@?BOb@WV??_@Ha@CC?c@c@_A}BUuAe@aEKgBMgBM_Bg@eHK{Aa@sDSmAoAeEC?]q@}DkFyA_A]G]O{@W}@Y?C_A_@?@gB{@gAa@iASc@Ee@Ii@G@?cEcAa@Oc@Q_Am@_B_AuAC[?{@BYC]Iu@ESDOTC?Bd@Df@?CRb@?@bA`Ah@Zt@R?AhBRz@Hz@@tBFvBHz@FdDr@p@RC?`Bx@fExB@?`BnAh@f@?B`GhG?@fAtAz@xAZd@Xf@Nf@Lj@Bj@?CGb@?BK\WLw@KW]Yi@a@m@uAcD@CA?sAgD]w@sA{C_@o@[g@B?sBoC]Y{DmB_@Qa@Wa@a@_@a@cAy@aAc@_Bg@eCg@?@a@OcB]YCa@GaA?YEa@B?>YF@?YHk@j@B?CC]F?>uA?oAG]AW?yB]WCS?S??BS@OP?@@?EV?`@C?H^Pb@T^tB\|A?CnBVzBA?AdAIfEq@\|D]hD[v@Ex@Bv@CfBHp@Rh@VtBxAnBhBxAz@lDxCb@f@dAfA`@`@Vb@Dd@Cf@?AU\[EB?C?]S_@g@?B}AwDa@o@eAsAc@Y?C{@k@B?[C?BSDIZB`@H\p@bAjAdA?CfBl@?BbBj@tAx@?B\|An@l@RxAj@A?h@Rf@R?BpBlA`@X^`@Z`@^\vApBh@rAPn@Df@Dh@A??A?f@QRYFB?WQY][k@B?uA{C[{@}@qB{@_BcAsABC_AqAwBuBkAgBm@_AW[YU@?YGSBC?SLI\A\C`@Df@B`@V\|AJn@?Bf@hBRt@rCpJb@pB?Cz@bDNt@Pp@@?d@lBC?t@hDRx@pAjGf@~C\dBt@\|Cp@tC`@zAXbBLt@^`B\nBn@~Ez@lITlBVlBHp@Lx@h@zEVrBHn@NfB?@f@dEz@nFBp@Eh@?Au@b@B?C?a@WA?[s@UeA[wAYiEWqIIcFKuL?yL?kBQwHScEE{AM_BOuAI}Aa@oDm@eGc@kDC?k@}CeAyEB?u@kCs@_CcAwBaAcBuC_DkAeA@?sBaBg@[iAw@mBsABB{@e@u@g@m@e@eAm@q@IYG[I{@k@{AsA]Wa@SaCyAoAk@WC?BSHIREX?\?@BA@`@Pd@?Cr@bA?A?@lA~@zAp@tCp@bBXjBZtCt@r@R`B`@l@VxFlBp@Rj@`@?Bb@\`@b@Xl@Hn@?C?l@C`@S`@?CUL[B]IcB{A?B}B{Ea@u@_@q@a@k@BCaBgC_@k@}AyBaCoBoCk@gFwA]KcASmBg@mBWwBCcBB_BD_AL_@D_Hd@Y>oAH?BiBX?AwATw@?_AU}BsAcBkAYMC?Y?[HOVE`@?f@@BA?Dl@Vd@C?hBrBbBZB?v@G~Bk@v@o@rBiBz@g@x@Wv@Cl@Hj@P`@XXf@CCLj@Df@A?@?St@OLYD?AsAk@eAm@B?gBcAa@[]SA?]Y{@u@?B]Ya@WyAiAyAy@]SwBk@aAW_CS{@?uAG"/>
</markers>

Would you please add the airport Laichingen EDPJ

Hello,

would you please be so kind to add Laichingen airport EDPJ to your list. Here are the datas (hopefully correct :-) )

'EDPJ'=> array('LAICHINGEN',"l.rec='EDPJ' AND l.alt < 1500 AND (l.lat BETWEEN 48.49120 AND 48.50380 ) AND (l.lon BETWEEN 9.623980 AND 9.656570)",742,''),

Many thank's in advance

Kind regards

Peter

flightlog optimization

Display of every pages of flightlog is very slow.
If i'm not wrong it compute all data for each display.
It may be possible to cache calculated information in another table?

Right click to select path length

For now, right click on a glider label display history path of the day.
It may be interesting to keep this feature but also if right clicking again, we can switch to 5' history, 10' history and then no history.

This will also allow to show path of a given glider and to erase it without reloading all the page.

README.md problems

The "source" link at the bottom of the "URL parameters" table is broken, the page it links to doesn't exist.

In the "AJAX endpoints" section in the second table, there is no description for the variable "recc" (says unknown)
"&r=SFVMa" only returns aircrafts that the receiver "SFVMa" received, so you could replace unknown with "receiver"

Please add a new airport LZTR

'LZTR'=> array('TRNAVA',"l.rec='LZTR' AND l.alt < 800 AND (l.lat BETWEEN 48.44731 AND 48.458623 ) AND (l.lon BETWEEN 17.536869 AND 17.522754)",200,''),

Please add airfield EDPD

Can you pleas add the airfield EDPD to aerolist.php

Here are the dates of the airfield
'EDPD'=> array('Dingolfing',"l.rec='EDPD' AND l.alt < 1055 AND (l.lat BETWEEN 48.65 AND 48.66 ) AND (l.lon BETWEEN 12.49 AND 12.51)",355,''),

Some ideas

That would be great idea to rewrite whole app to some framework- backend and frontend. Because after a while it will be unsustainable.

  • create some registration, login and flighbook
  • manage own gliders
  • create and manage competitions
  • if there is a random CN that would be great to set it manually just for me or competition
  • echoing whole page may be slower than dropping it out of php and also readability of code is better :). Referring to http://php.net/manual/en/language.basic-syntax.phpmode.php
  • add some points of interest on map- airports, restricted areas...
  • refactor code and translate some parts to english :)

Offline glider labels shifted north

Hi,

since the introduction of "Altitude stick" feature, when we uncheck "Ignore Offline", all offline labels are shifted to north as if the "Altitude stick" was checked (bit it is not checked).

So if you right click on the label loading the history track, you see the offset as on folwing picture:

image

There is no issue with online gliders.

Thanks

HTTPS not supported

live.glidernet.org does not load over HTTPS. This should be easy to setup using Lets Encrypt just like the glidernet.org homepage uses

Autocenter via URL-Parameter

Hi Guys,
Great work, thanks so much!

i was wondering, is there a way to request a autocenter to a specific Flarm/OGN-ID-Glider via a URL-Parameter?
as far as i can read the code there are currently only the Parameters

hashc="",hashz="",hashm="",hasho="",hashb="",hashs="",hashl="",hasht="",hl=" ",hashw="",hashu="",hashp="",hashn=""
interpreted.

Would be great to have such a feature to enable website viewers to directly zoom to "their" Aircraft, or get an errormessage if it was currently not tracked...
Volker

Please add EDMD to airfield list

Hi cunimb,

could you please add the airfield EDMD into the aerolist? (also see my pull req)

Here's the string to add:

'EDMD'=> array('Dachau-Groebenried',"l.rec='EDMD' AND l.alt < 1190 AND (l.lat BETWEEN 48.2285 AND 48.2485 ) AND (l.lon BETWEEN 11.4262 AND 11.4462)",490,''),

Thanks in advance!

Pls add airfield "Mönchsheide" (receiver "Heide") to FlightLog

Could someone be so kind to add airfield "Mönchsheide" (receiver "Heide") to FlightLog. Parameters should be the following:

'Mönc'=> array('Mönchsheide',"l.rec='Heide' AND l.alt < 904 AND (l.lat BETWEEN 50.50675 AND 50.50931 ) AND (l.lon BETWEEN 7.2498 AND 7.2622)",204,''),

Thanks in advance!

Regards
David

Airspace display does not work

according to #3 there should be some sort of airspace layer visible on top of the map, but it doesn't seem to work for me. is this feature broken or do I need to be logged in at OpenAIP or what is the problem here?

Outdates flight tracks pile up on screen borders

When I leave live.glidernet.org running for a longer while, a significant number of outdated flight tracks pile up on the screen boarders and are not earased after 5 min.
Screen Shot 2021-08-12 at 21 48 01
It seems, that when an aircraft is leaving the screen area, it's track is not deleted/shortened according to the defined timing criteria, but processing of the respective flight track stops.

Desriable behaviour would be, that the flight track is shortend accoring to timing criteria although the aircraft has already left the screen area.

Database issues

Hi everyone,

Iam getting the following issues.:

( ! ) Notice: Undefined variable: params in C:\wamp\www\test\index.php on line 30
Call Stack

Time Memory Function Location

1 0.0000 250864 {main}( ) ..\index.php:0

( ! ) Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42S02]: Base table or view not found: 1146 Table 'flarm.live' doesn't exist' in C:\wamp\www\test\index.php on line 30
( ! ) PDOException: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'flarm.live' doesn't exist in C:\wamp\www\test\index.php on line 30

I this because I don't have the database structure, if yes, where do I get it?

Thanks in advance

please add Bensheim to the airfield list

'BENSH' => array('Bensheim',"l.rec='Bensheim' AND (l.alt < 795) and (l.lat BETWEEN 49.689452 AND 49.696209) AND (l.lon BETWEEN 8.574639 AND 8.588647)", 95,''),

Thank you!

Please add airfield EDSV

Dear all,

I like to add our new installed receiver to OGN flight log. Its a glider airfield in southern Germany, receiver is up and working, I only have to connect the antenna to our tower. For that I can’t transmit FLARM signals right now, will be fixed in the next weeks.

Please provide the ranges of parameter I have to define.

Receiver: EDSV
Latitude: +486156170
Longitude: +87544880
Altitude Airfield: 600m, Antenna 10 m above ground

Add Airfield Oppershauen

Hi, would it be possible to add our Airfield "Oppershausen" to the list at http://flightlog.glidernet.org/ ?

Airfield code: "OHAUSEN" (its not a real code, but its a small glider-airfield and i used that name on the receiver-list too)
Location: N52.596104, E10.215123
Altitude: 43m
Time zone: GMT +1:00
Airfield owner: Flugplatzgemeinschaft Oppershausen

The receiver worked fine in a testrun and will hopefully be up and running starting this season ;-)
Please ask if you need any more information.

greetings from Hannover,
Chris

Local airspace files

Hi, is it possible to use own airspace file?
E.g. You have customized SUA file, with some borders for reservations, which pilots use in their NavPrograms, but you need to be sure if they are outside of this airspace or not, because you need to coordinate with another airspace operator...

Menu don't respond when all devices are filtered

http://live.glidernet.org/#c=47.50850,6.63969&z=6&y=0

When y=0 the backend return no datas and the frontend crash in cunimb.js#L842

Empty result (no OGN devices at that time): 👍
http://live.glidernet.org/lxml.php?a=0&z=1&y=4

<markers></markers>

Empty result (no OGN devices at that time): 👎
http://live.glidernet.org/lxml.php?a=0&z=1&y=0

Result with some ICAO receivers : 👍
http://live.glidernet.org/lxml.php?a=0&z=1&y=1

<markers>
<m a="48.599030,8.525970,_5e,89a12f5e,1934,13:25:30,15,20,181,-0.8,1,Musbach,0,89a12f5e"/>
<m a="52.783150,7.533330,_13,c31cb513,1492,13:25:32,13,347,309,-1.6,8,Veendam,0,c31cb513"/>
<m a="51.019619,8.033680,_39,df562339,1279,13:15:11,634,27,219,-2.6,7,Wenscht,0,df562339"/>
</markers>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.