ornot.vote
hosted:
ใกใผใซใขใใฌใน่ใใฆใใพใใใ่ช่จผใฎใใใ ใใงใใใใใใทใฅใใกใใใฎใงใไฟๅญใฏใใใพใใใใตใผใใผใณใผใๅ็ งใฎใใจใ่ช่จผใฏ di (ไธไบใใ)ใจใคใชใใใใจใใใ
it’s open sourced:
- https://github.com/yasushisakai/ornot-server
- https://github.com/yasushisakai/ornot-app
- https://github.com/yasushisakai/liq
used for:
- makuhari city ws
- epa: details to come
- shibuya
1 DONE other ’votable’s
- url
- image
- geolocation
- point
- geofences
ref: votables
curl localhost:8080/api/v1/user/8VYVEzNLAQ6fYVpLAUe354LJ6FnJyLyoYXhQ8MqHdi6B/code/29Ktx5iSqaUxo6CDczEbUbgx2qXvQnGRUX5Ke63AUZnGx97VPHJpCHJNZrau9PiQ13dFKVpHoPutb2qRjs3KiQDh
1.1 directly add a plan to topic
a sane way to add a plan is to directly add it to an existing topic. this endpoint shows you how.
first, add a new topic
curl -X PUT -d '{"title":"test", "description":"a test topic"}' -H "Content-Type:application/json" localhost:8080/api/v1/topic | jq
“5E2syfDP3qqxessoAQww6u3kQW3TrSU3Wg1NJVNLV8x3”
then add a new plan to that topic
for the different plan types, the following examples will show in various cases. this case is using a simple plan.
curl -X POST -d '{"type":"simple", "data":"test plan"}' -H "Content-Type:application/json" localhost:8080/api/v1/topic/5E2syfDP3qqxessoAQww6u3kQW3TrSU3Wg1NJVNLV8x3/new_plan
curl -X POST -d '{"type":"image", "data":"https://yasushisakai.com/images/me_2019_square.jpg"}' -H "Content-Type:application/json" localhost:8080/api/v1/topic/ryfJLbHJQ3tjcWn9sAYJDkz3NNpEMck3oZR5iBK4Cec/new_plan
[“5E2syfDP3qqxessoAQww6u3kQW3TrSU3Wg1NJVNLV8x3”,“FP3FzRKprwjoDMRjTQ1X4thLEzeUJyHX5mrGCCrEACRi”]
this will return the topic id and the plan id.
1.2 simple example
curl -x put -d '{"type":"simple", "data":"simple plan example"}' -h "content-type: application/json" http://localhost:8080/api/v1/plan
“gmq8jjszakwdv53laeg6zhvcsmwgeyugwgfsbz46uib”
curl -x get http://localhost:8080/api/v1/plan/gmq8jjszakwdv53laeg6zhvcsmwgeyugwgfsbz46uib
{“type”:“simple”,“data”:“simple plan example”}
1.3 long example (with description)
curl -x put -d '{"type":"long", "data":["long plan example","longer description showing what this is"]}' -h "content-type: application/json" http://localhost:8080/api/v1/plan
“hledzqqm166yqyarhnplbmfznw3qq1ge4pmhn9kah4ql”
curl -x get http://localhost:8080/api/v1/plan/hledzqqm166yqyarhnplbmfznw3qq1ge4pmhn9kah4ql | jq .
{ “type”: “long”, “data”: [ “long plan example”, “longer description showing what this is” ] }
1.4 url example (with description)
curl -x put -d '{"type":"url", "data":["yasushi", "https://yasushisakai.com"]}' -h "content-type: application/json" http://localhost:8080/api/v1/plan
“ek4ox9usaayawbycwamm48h14n8sdyys7cllubg7mehp”
curl -x get http://localhost:8080/api/v1/plan/ek4ox9usaayawbycwamm48h14n8sdyys7cllubg7mehp | jq .
{ “type”: “url”, “data”: [ “yasushi”, “https://yasushisakai.com” ] }
1.5 image example
curl -x put -d '{"type":"image", "data":"https://yasushisakai.com/images/me_2019_square.jpg"}' -h "content-type: application/json" http://localhost:8080/api/v1/plan
“co5taruclmx3rxp2zy5y191rzzjmwjhfjwrb3ypfhnm8”
curl -x get http://localhost:8080/api/v1/plan/co5taruclmx3rxp2zy5y191rzzjmwjhfjwrb3ypfhnm8
{“type”:“image”,“data”:“”}
1.6 latlng example
curl -x put -d '{"type":"latlng", "data":["mit media lab", {"lat":42.3515853, "lng":-71.1335335}]}' -h "content-type: application/json" http://localhost:8080/api/v1/plan
“32nj9etbotgdfcsznhh3ngeyvm3thj8ujrhcs2eqtswu”
the first element should be a string or null.
curl -x get http://localhost:8080/api/v1/plan/32nj9etbotgdfcsznhh3ngeyvm3thj8ujrhcs2eqtswu
{“type”:“latlng”,“data”:[“mit media lab”,{“lat”:42.3515853,“lng”:-71.1335335}]}
1.7 circular geofence example
curl -x put -d '{"type":"circle", "data":["keio sfc", {"lat": 35.3881712, "lng": 139.4254151, "radius": 30}]}' -h "content-type: application/json" http://localhost:8080/api/v1/plan
“2byjbwbkx48ayu2qfweykg78wkss5fwsvxnen5danzqe”
curl -x get http://localhost:8080/api/v1/plan/2byjbwbkx48ayu2qfweykg78wkss5fwsvxnen5danzqe | jq .
{ “type”: “circle”, “data”: [ “keio sfc”, { “lat”: 35.3881712, “lng”: 139.4254151, “radius”: 30 } ] }
1.8 path example
curl -x put -d '{"type":"path", "data":[null, [[35.3881712,139.4254151],[42.3515853,-71.1335335]]]}' -h "content-type: application/json" http://localhost:8080/api/v1/plan
“bqvwfn2ayxcdaiaachecu5kj5knawbjabktpxamtfz14”
curl -x get http://localhost:8080/api/v1/plan/bqvwfn2ayxcdaiaachecu5kj5knawbjabktpxamtfz14 | jq .
{ “type”: “path”, “data”: [ null, [ [ 35.3881712, 139.4254151 ], [ 42.3515853, -71.1335335 ] ] ] }
2 TODO cool user graphical interface
use p5js or hand crafted svgs?
3 TODO make it possible to trace votes
the data structure holds a forward chain, but the front end does not let us see it.
4 TODO look for cuda implementation for the matrix manipulation
the calculation is simple enough
5 DONE restore database
6 DONE dump data base
there should be an endpoint for dumping the whole thing.
curl localhost:8080/api/v1/dump
will output a tuple
you can back up the redis itself too… redis
7 DONE refactor model
model.rs is complex enough to be a directory
8 DONE svelte side
general refactoring is needed
9 DONE settings should just link to result
want to make a forward chain data structure within results
setting : □ → □ → □ ↓ ↓ ↓ results : ◆ ◆ ◆
to make sure it’s reproducible, we need to get the commit it of the program.
10 DONE nuclear handle with care!!
this deletes everything.
curl -x delete https://ornot.vote/api/v1/nuclear
11 DONE make token:userid data base
auth relying on get-ing the whole user object, which i should hold a separate look up
that has access_token:user_id
partially because often times i’m requesting user data for different purposes.
we now have the access_token:user_id
but each time someone clear caches and tries to register their nickname,
we make another temp code which trickles down to a new accesstoken
to address this, we need invalidate(del) the previous tempcode
12 DONE tokens, codes should be base58
13 DONE apis for auth
user asks for a temp code
jq
is just to pretty print the output. this will send a email to the address specified. that email will have a url such a as thiscurl -x post -d '{"nickname":"yasushi", "email":"yasushisakai@pm.me"}' -h "content-type:application/json" https://ornot.vote/api/v1/user/signup | jq
hi yasushi, this is a tiny note to let you know your temp code. use the below url to verify that you own this email address. {url} bye and have a nice day :)
check the temp code
curl https://ornot.vote/api/v1/user/hehyiu6kwziwgavazt4ywv38hneujn2dljsysaywzoys/code/265ugadf9gt1a7b7xpmsbobnpxyvy4d31pw14nhz5t5r1qgw6ls5xyebyml4lwtregpddq6rjlbsrxqx8wuwal2p | jq
"32azk7dl48kcwaivptcmeeyj7fhn53lmjlmatckbpmb5v7ftmhqlnrjyyqkr6yysckrjk2hvkeeaa738n8envkrr"
the user now has an access token. we check that putting that in subsequent requests.
authorize with access token
curl -h "authorization: bearer 2y6xdnsvwdkldspg6sqbvkrxpyaqiu5gpdcht47ehycpbofatmef6bsntmyvxrdpbdd9zbevmrnfczjnerqs8svm" https://ornot.vote/api/v1/user/4x2n89y3gujoy3vwmtmn2zjuxwwpmrqxbdoaappbnvtd/check
yes
testing out the master key
curl -h "authorization: bearer secret" https://ornot.vote/api/v1/user/4x2n89y3gujoy3vwmtmn2zjuxwwpmrqxbdoaappbnvtd/check
14 DONE force add users
curl -x post -d '{"nickname":"yasushi", "email":"yasushisakai@pm.me"}' -h "content-type:application/json" https://ornot.vote/api/v1/user/signup | jq
curl -x post -d '{"nickname":"yasushi", "email":"yasushisakai@pm.me"}' -h "content-type:application/json" https://ornot.vote/api/v1/user/force_add | jq
15 DONE debugging (normal path)
curl -X POST -d '{"nickname":"alice", "email":"alice@test.com"}' -H "Content-Type:application/json" https://ornot.vote/api/v1/user/force_add && \ curl -X POST -d '{"nickname":"bob", "email":"bob@test.com"}' -H "Content-Type:application/json" https://ornot.vote/api/v1/user/force_add && \ curl -X POST -d '{"nickname":"charlie", "email":"charlie@test.com"}' -H "Content-Type:application/json" https://ornot.vote/api/v1/user/force_add
[{"id":"LDF8e1kPPSHxviRCXDTdjc4KiYyum1sWtFQFoZioPzH","nickname":"alice","is_verified":true},"2zG6TzEWdwWj9vMNELVMmm9broh5JK2HYssH9gRbuFsBzYVRHNQzSuKm3jXzmHM716uLYfuSoKqdGJnH4Jjujo5u"][{"id":"HUTPBwX93cis679hzKbaKdW1JTDmdJRbmcRutMiMwyvE","nickname":"bob","is_verified":true},"2whsQZfiXxWQAWSKThx24szqYev3LkBMMs8xafkcXtATbmjaEcyiLUuQBahaj3yU9QdYewAHt5Uo4LA3JC4MFfde"][{"id":"J68FXm8HDZkN3e8gNMVrm7Kg75Krz9QCg1Nf8JZSADDW","nickname":"charlie","is_verified":true},"2xthzEUftUFdEnJS9xBNcKeewuK4HcTvohArsSJ9HqkP4k88LeN9Cz7BbQM13NrvCJtfnSz6oBWqaCizMkf8iVgR"]
adding a topic
curl -X PUT -d '{"title":"What to eat for breakfast", "description":"what to eat today"}' -H "Content-Type:application/json" https://ornot.vote/api/v1/topic | jq
adding a users to a topic
curl -X POST https://ornot.vote/api/v1/topic/EFc3ubcwZFtF73gqhgVHWVtJdsPNSita1B2rf8LdmFVB/user/J68FXm8HDZkN3e8gNMVrm7Kg75Krz9QCg1Nf8JZSADDW && \ curl -X POST https://ornot.vote/api/v1/topic/EFc3ubcwZFtF73gqhgVHWVtJdsPNSita1B2rf8LdmFVB/user/HUTPBwX93cis679hzKbaKdW1JTDmdJRbmcRutMiMwyvE && \ curl -X POST https://ornot.vote/api/v1/topic/EFc3ubcwZFtF73gqhgVHWVtJdsPNSita1B2rf8LdmFVB/user/LDF8e1kPPSHxviRCXDTdjc4KiYyum1sWtFQFoZioPzH
get topic info
curl -X GET https://ornot.vote/api/v1/topic/EFc3ubcwZFtF73gqhgVHWVtJdsPNSita1B2rf8LdmFVB | jq
{ "id": "EFc3ubcwZFtF73gqhgVHWVtJdsPNSita1B2rf8LdmFVB", "title": "What to eat for breakfast", "description": "what to eat today", "setting_hash": "FxJpTuXF39AUf5LYtUJvenXAotXiNM26qqPnBQBstUGt", "setting_prev_hash": "Gw7GroDLi62unVKGhJzd7cbxxvp42rcnvTwqqaWXVjye", "setting": { "voters": [ "J68FXm8HDZkN3e8gNMVrm7Kg75Krz9QCg1Nf8JZSADDW", "HUTPBwX93cis679hzKbaKdW1JTDmdJRbmcRutMiMwyvE", "LDF8e1kPPSHxviRCXDTdjc4KiYyum1sWtFQFoZioPzH" ], "plans": [ { "title": "cereal", "description": null }, { "title": "bread", "description": null }, { "title": "rice", "description": null }, { "title": "left_over_pizza", "description": null } ], "votes": { "HUTPBwX93cis679hzKbaKdW1JTDmdJRbmcRutMiMwyvE": { "bread": 0.4, "cereal": 0.2, "left_over_pizza": 0.1, "rice": 0.3 }, "LDF8e1kPPSHxviRCXDTdjc4KiYyum1sWtFQFoZioPzH": { "HUTPBwX93cis679hzKbaKdW1JTDmdJRbmcRutMiMwyvE": 0.5, "bread": 0.3, "left_over_pizza": 0.2 } } }, "result": { "votes": { "(Blank)": 1, "bread": 0.8999999999999999, "cereal": 0.29999999999999993, "left_over_pizza": 0.35, "rice": 0.4499999999999999 }, "influence": { "HUTPBwX93cis679hzKbaKdW1JTDmdJRbmcRutMiMwyvE": 1.5, "J68FXm8HDZkN3e8gNMVrm7Kg75Krz9QCg1Nf8JZSADDW": 1, "LDF8e1kPPSHxviRCXDTdjc4KiYyum1sWtFQFoZioPzH": 1 } } }
add some plans
curl -X POST https://ornot.vote/api/v1/topic/EFc3ubcwZFtF73gqhgVHWVtJdsPNSita1B2rf8LdmFVB/plan/cereal && \ curl -X POST https://ornot.vote/api/v1/topic/EFc3ubcwZFtF73gqhgVHWVtJdsPNSita1B2rf8LdmFVB/plan/bread && \ curl -X POST https://ornot.vote/api/v1/topic/EFc3ubcwZFtF73gqhgVHWVtJdsPNSita1B2rf8LdmFVB/plan/rice && \ curl -X POST https://ornot.vote/api/v1/topic/EFc3ubcwZFtF73gqhgVHWVtJdsPNSita1B2rf8LdmFVB/plan/left_over_pizza
vote and calculate
curl -X PUT -d '{"cereal": 0.2, "rice": 0.3, "bread": 0.4, "left_over_pizza":0.1}' -H "Content-Type:application/json" https://ornot.vote/api/v1/topic/EFc3ubcwZFtF73gqhgVHWVtJdsPNSita1B2rf8LdmFVB/vote/HUTPBwX93cis679hzKbaKdW1JTDmdJRbmcRutMiMwyvE | jq
curl -X PUT -d '{"HUTPBwX93cis679hzKbaKdW1JTDmdJRbmcRutMiMwyvE": 0.2, "LDF8e1kPPSHxviRCXDTdjc4KiYyum1sWtFQFoZioPzH": 0.8}' -H "Content-Type:application/json" https://ornot.vote/api/v1/topic/EFc3ubcwZFtF73gqhgVHWVtJdsPNSita1B2rf8LdmFVB/vote/J68FXm8HDZkN3e8gNMVrm7Kg75Krz9QCg1Nf8JZSADDW | jq
curl -X PUT -d '{"HUTPBwX93cis679hzKbaKdW1JTDmdJRbmcRutMiMwyvE":0.5, "left_over_pizza":0.2, "bread":0.3}' -H "Content-Type:application/json" https://ornot.vote/api/v1/topic/EFc3ubcwZFtF73gqhgVHWVtJdsPNSita1B2rf8LdmFVB/vote/LDF8e1kPPSHxviRCXDTdjc4KiYyum1sWtFQFoZioPzH | jq
second time should not calculate
curl -X PUT -d '{"HUTPBwX93cis679hzKbaKdW1JTDmdJRbmcRutMiMwyvE":0.5, "left_over_pizza":0.2, "bread":0.3}' -H "Content-Type:application/json" https://ornot.vote/api/v1/topic/EFc3ubcwZFtF73gqhgVHWVtJdsPNSita1B2rf8LdmFVB/vote/LDF8e1kPPSHxviRCXDTdjc4KiYyum1sWtFQFoZioPzH | jq
16 DONE get setting, raw calculate
curl -X GET https://ornot.vote/api/v1/setting/Gw7GroDLi62unVKGhJzd7cbxxvp42rcnvTwqqaWXVjye
curl -X POST -H "Content-Type:application/json" -d '{"voters":["J68FXm8HDZkN3e8gNMVrm7Kg75Krz9QCg1Nf8JZSADDW","HUTPBwX93cis679hzKbaKdW1JTDmdJRbmcRutMiMwyvE","LDF8e1kPPSHxviRCXDTdjc4KiYyum1sWtFQFoZioPzH"],"plans":[{"title":"cereal","description":null},{"title":"bread","description":null},{"title":"rice","description":null},{"title":"left_over_pizza","description":null}],"votes":{"HUTPBwX93cis679hzKbaKdW1JTDmdJRbmcRutMiMwyvE":{"bread":0.4,"cereal":0.2,"left_over_pizza":0.1,"rice":0.3}}}' https://ornot.vote/api/v1/calculate_raw | jq
curl -X POST -H "Content-Type:application/json" -d '{"voters":["alice","bob","charlie"],"plans":["cereal","egg","bread"],"votes":{"alice":{"bread":0.4,"cereal":0.2,"egg":0.1,"rice":0.3}, "bob":{"alice":0.5, "bread":0.5}}}' https://ornot.vote/api/v1/calculate_raw | jq
{ "votes": { "(Blank)": 2, "bread": 0.3999999999999999, "cereal": 0.19999999999999996, "left_over_pizza": 0.09999999999999998, "rice": 0.29999999999999993 }, "influence": { "HUTPBwX93cis679hzKbaKdW1JTDmdJRbmcRutMiMwyvE": 1, "J68FXm8HDZkN3e8gNMVrm7Kg75Krz9QCg1Nf8JZSADDW": 1, "LDF8e1kPPSHxviRCXDTdjc4KiYyum1sWtFQFoZioPzH": 1 } }