Entitlements user interaction designs and proof of concept

entitlements.org 53KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961
  1. * Introduction
  2. The purpose of this document is to investigate possible User Interaction designs for Decode task 4.4.
  3. More specifically the focus is on investigating how the user of a decode wallet grants permission to decode application for a specific set of personal data.
  4. A prelimary definition of six privacy levels (ordered from most private to least private):
  5. - SECRET: passwords, keys etc.
  6. - PRIVATE: ssn etc, strict need to know basis stuff
  7. - INTIMATE: e.g. stuff you share with family
  8. - AFFILIATE: e.g. stuff you share with work, project etc
  9. - PUBLIC: e.g. stuff that everybody may know, your e.g. twitter handle
  10. - COMMONS: stuff that is intended for the public good / commons, e.g. anonimized IoT stuff
  11. A preliminary definition of context types
  12. - PERSONAL: data that relates to your personal life, you can have different instances, for example friends, family etc.
  13. - HEALTH: health data, you can define different instances (biosignals, stuff to share with dentist, gp, hospital etc)
  14. - EDUCATION: school / educational data (grades, certificates etc)
  15. - WORK: stuff you share in a professional context
  16. - HOBBY: stuff you share in the context of a pastime
  17. - FINANCIAL: for data about mortgages, insurance, taxes etc.
  18. - OTHER: for everything that doesn't fit the above
  19. * Data Model
  20. ** Example wallet profile
  21. This sample wallet profile datastructure consists of multiple contexts.
  22. No assumptions are made about ontology for now so mention of existing e.g. skos/foaf,
  23. everything is in the decode namespace which is well known across applications.
  24. Each context has a name and groups on or more properties that consist of a well known type and a value.
  25. A type can be part of more than one context.
  26. Every property instance has a privacy level attached to it, so we can calculate the weight of requests and profiles.
  27. It overrides the default privacy level specified by the property type.
  28. #+name: profile
  29. #+begin_src js :results output
  30. var profile = {
  31. contexts :
  32. [
  33. {
  34. title : "personal",
  35. context_type : 5,//PERSONAL
  36. properties :
  37. [
  38. {
  39. type : "decode:name",
  40. value: "Taco van Dijk",
  41. pl: 1 //public, everyone may know my name
  42. },
  43. {
  44. type : "decode:email",
  45. value : "[REDACTED]",
  46. pl: 2 //affiliate, parties i have personal business with may know
  47. },
  48. {
  49. type: "decode:address",
  50. value: "[REDACTED]",
  51. pl: 2 //affiliate, parties i have personal business with may know
  52. },
  53. {
  54. type: "decode:phone",
  55. value : "[REDACTED]",
  56. pl: 2 //affiliate, parties i have personal business with may know
  57. }
  58. ],
  59. pl_sum: 7 //this is a calculated value based on the attributed pl values or default if they were not user specified
  60. },
  61. {
  62. title: "Waag society",
  63. context_type: 2,//WORK
  64. properties :
  65. [
  66. {
  67. type : "decode:name",
  68. value : "Taco van Dijk",
  69. pl: 1
  70. },
  71. {
  72. type : "decode:email",
  73. value : "taco@waag.org",
  74. pl: 2
  75. },
  76. {
  77. type : "decode:address",
  78. value : "St. Antoniesbreestraat 69",
  79. pl: 1 //since this is shared with all my colleagues i find this public
  80. }
  81. ],
  82. pl_sum: 4
  83. },
  84. {
  85. title: "Dyne",
  86. context_type: 2,//WORK
  87. properties :[{
  88. type : "decode:name",
  89. value : "Ocat",
  90. pl: 1
  91. },
  92. {
  93. type : "decode:email",
  94. value: "taco@gogs.dyne.org",
  95. pl: 2
  96. }
  97. ],
  98. pl_sum: 3
  99. }
  100. ]
  101. };
  102. process.stdout.write(JSON.stringify(profile));
  103. #+end_src
  104. #+RESULTS: profile
  105. : {"contexts":[{"title":"personal","context_type":5,"properties":[{"type":"decode:name","value":"Taco van Dijk","pl":1},{"type":"decode:email","value":"[REDACTED]","pl":2},{"type":"decode:address","value":"[REDACTED]","pl":2},{"type":"decode:phone","value":"[REDACTED]","pl":2}],"pl_sum":7},{"title":"Waag society","context_type":2,"properties":[{"type":"decode:name","value":"Taco van Dijk","pl":1},{"type":"decode:email","value":"taco@waag.org","pl":2},{"type":"decode:address","value":"St. Antoniesbreestraat 69","pl":1}],"pl_sum":4},{"title":"Dyne","context_type":2,"properties":[{"type":"decode:name","value":"Ocat","pl":1},{"type":"decode:email","value":"taco@gogs.dyne.org","pl":2}],"pl_sum":3}]}
  106. *** Things to further investigate
  107. - Apply default weights to each property type, these can be overridden by attributing a privacy level to the property
  108. - Make a big list of possible property types (at least properties that are used in Gebied Online)
  109. - Make a big list of possible context names
  110. - Create a generator that seeds profiles with random contexts from the aforementioned lists.
  111. ** Example request
  112. This sample application request consists of an application name, a set of required property types and a set of optional property types.
  113. Each application has a default context type attached to it, (so we can assign it a hue).
  114. For each request we can calculate the average privacy level,
  115. and the cumulative privacy weight by adding the privacy levels of each property in the request.
  116. #+name: request
  117. #+BEGIN_SRC js :results output
  118. var request = {
  119. application : "decodeapp:facebook",
  120. context_type : 5,//personal
  121. required : ["decode:name", "decode:email", "decode:address"],
  122. optional : ["decode:phone"]
  123. }
  124. var data = JSON.stringify(request) + "\n";
  125. process.stdout.write(data);
  126. #+END_SRC
  127. #+RESULTS: request
  128. : {"application":"decodeapp:facebook","context_type":0,"required":["decode:name","decode:email","decode:address"],"optional":["decode:phone"]}
  129. *** Things to further investigate
  130. - Create a generator that seeds a request with random required and optional property types
  131. - Calculate the weight of the request
  132. * Data Comparison
  133. During the interaction we want to give the user insight into a couple of things;
  134. - How does the requested set of properties relate to the different contexts? How well does a context match to the request?
  135. - What would it mean for the context if the request was accepted? How many / which properties would have to be added to the context in order to fulfill the request?
  136. - What would it mean for the cumulative weight of the context?
  137. In below ruby code a comparison is made by on creating the intersection and its inverse between the request and each context.
  138. #+name: diff_src
  139. #+BEGIN_SRC ruby
  140. require 'json'
  141. require 'nokogiri' #for creating xml
  142. request = JSON.parse(request_data)
  143. profile = JSON.parse(profile_data)
  144. context_diffs = []
  145. profile["contexts"].each do | context |
  146. requested = request["required"] + request["optional"]
  147. available = context["properties"].map {|p| p["type"]}
  148. intersect = available & requested
  149. except = requested - available
  150. diff = {:context => context["title"], :intersect => intersect, :except => except}
  151. context_diffs << diff
  152. end
  153. #+END_SRC
  154. #+RESULTS: diff_src
  155. #+name: xml
  156. #+BEGIN_SRC ruby :exports none
  157. # unfortunately processing.js doesn't support json yet, so we have to use xml
  158. doc = Nokogiri::XML::Builder.new do |xml|
  159. xml.result {
  160. xml.request {
  161. xml.application request["application"]
  162. xml.contextType request["context_type"]
  163. xml.required {
  164. request["required"].each do |p| xml.property p end
  165. }
  166. xml.optional {
  167. request["optional"].each do |p| xml.property p end
  168. }
  169. }
  170. xml.diffs {
  171. context_diffs.each do |diff|
  172. xml.diff {
  173. xml.contextName diff[:context]
  174. xml.intersect {
  175. diff[:intersect].each do |p| xml.property p end
  176. }
  177. xml.except {
  178. diff[:except].each do |p| xml.property p end
  179. }
  180. }
  181. end
  182. }
  183. xml.profile {
  184. profile["contexts"].each do | context |
  185. xml.contextObj {
  186. xml.contextName context["title"]
  187. xml.contextType context["context_type"]
  188. xml.plSum context["pl_sum"]
  189. xml.properties {
  190. context["properties"].each do |property|
  191. xml.property {
  192. xml.type property["type"]
  193. xml.value property["value"]
  194. xml.pl property["pl"]
  195. }
  196. end
  197. }
  198. }
  199. end
  200. }
  201. }
  202. end
  203. path = "diff.xml"
  204. File.write(path, doc.to_xml)
  205. path
  206. #+END_SRC
  207. #+RESULTS: xml
  208. #+name: diff
  209. #+BEGIN_SRC ruby :exports none :noweb yes :var profile_data=profile :var request_data=request :results value file
  210. <<diff_src>>
  211. <<xml>>
  212. #+END_SRC
  213. #+RESULTS: diff
  214. [[file:diff.xml]]
  215. *** Things to further investigate
  216. - Calculate the weight (sum of privacy levels of the properties it contains) of each context before and after giving permission
  217. NOTE: We export to file diff.xml here for easy parsing in processing.js below.
  218. /de relatieve grootte van de cirkel kan zijn op basis van hoeveel data je erin hebt.
  219. personal is size 4, professional size 3
  220. request is size 3
  221. * Visualization
  222. We want to visualize the following things;
  223. - The request with the application name and it's size / quality (Who's asking what)
  224. - The different contexts with it's name and size / quality relative to the request. (What would it mean to accept?)
  225. Per the design of Dyne, we want to use color to indicate the relation between the request and each context.
  226. A color should indicate something about privacy level and context type.
  227. For now the mapping is as follows;
  228. Different hues can be mapped to each context type.
  229. Different tones within the hue can be mapped to each privacy level.
  230. #+name: colors
  231. #+BEGIN_SRC java
  232. //color definitions
  233. color a3 = #3A3B58;
  234. color b3 = #734246;
  235. color d3 = #B4561F;
  236. color c3 = #336F60;
  237. color f3 = #7A3E2A;
  238. color g3 = #A48137;
  239. color e2 = #97BBCB;
  240. color a4 = #3B4257;
  241. color b4 = #6A4345;
  242. color d4 = #86451F;
  243. color c4 = #345A48;
  244. color f4 = #A92F21;
  245. color g4 = #BC983B;
  246. color a5 = #3D4358;
  247. color b5 = #402623;
  248. color d5 = #85442D;
  249. color c5 = #3B403A;
  250. color f5 = #7A150B;
  251. color g5 = #252F2B;
  252. color a1 = #597099;
  253. color e4 = #0A3878;
  254. color b1 = #D16365;
  255. color d1 = #FFD43B;
  256. color c1 = #B7BF98;
  257. color e1 = #CAD2C8;
  258. color e0 = #F5EDE5;
  259. color f1 = #D17978;
  260. color g1 = #FDD23E;
  261. color a0 = #C5C3CC;
  262. color e3 = #0485B1;
  263. color b0 = #FFDCD6;
  264. color d0 = #FFE9BE;
  265. color c0 = #F0E9D5;
  266. color f0 = #E4C8BF;
  267. color g0 = #FBE6BA;
  268. color a2 = #3D4B79;
  269. color e5 = #084064;
  270. color b2 = #974244;
  271. color d2 = #F8AA08;
  272. color c2 = #4E937F;
  273. color f2 = #8F4330;
  274. color g2 = #FFDB03;
  275. color colors[][] = {
  276. {b0,b1,b2,b3,b4,b5},
  277. {c0,c1,c2,c3,c4,c5},
  278. {a0,a1,a2,a3,a4,a5},
  279. {d0,d1,d2,d3,d4,d5},
  280. {e0,e1,e2,e3,e4,e5},
  281. {f0,f1,f2,f3,f4,f5},
  282. {g0,g1,g2,g3,g4,g5}
  283. };
  284. class PrivacyLevel {
  285. public static int SECRET = 5;
  286. public static int PRIVATE = 4;
  287. public static int INTIMATE = 3;
  288. public static int AFFILIATE = 2;
  289. public static int PUBLIC = 1;
  290. public static int COMMONS = 0;
  291. }
  292. class ContextType {
  293. public static int FINANCIAL = 6;
  294. public static int PERSONAL = 5;
  295. public static int HEALTH = 4;
  296. public static int EDUCATION = 3;
  297. public static int WORK = 2;
  298. public static int HOBBY = 1;
  299. public static int OTHER = 0;
  300. }
  301. public int getColor(int privacy_level, int context_type)
  302. {
  303. return colors[context_type][privacy_level];
  304. }
  305. #+END_SRC
  306. Below snippet exemplifies a color for the SELF context with a privacy level SECRET, and should be a dark red color.
  307. #+name: color_example_src_1
  308. #+BEGIN_SRC java
  309. void draw(){
  310. size(100,100);
  311. background(0);
  312. noStroke();
  313. int level = PrivacyLevel.SECRET;
  314. int contextType = ContextType.PERSONAL;
  315. color secret_self = getColor(level, contextType);//expect dark red
  316. fill(secret_self);
  317. ellipse(50,50,50,50);
  318. }
  319. #+END_SRC
  320. #+name: color_example_1
  321. #+BEGIN_SRC processing :noweb yes
  322. <<colors>>
  323. <<color_example_src_1>>
  324. #+END_SRC
  325. #+RESULTS: color_example_1
  326. #+BEGIN_EXPORT html
  327. <script src="processing.js"></script>
  328. <script type="text/processing" data-processing-target="ob-e4084f25c6566c618f6cc091e4920fd86e9b1c21">
  329. //color definitions
  330. color a3 = #3A3B58;
  331. color b3 = #734246;
  332. color d3 = #B4561F;
  333. color c3 = #336F60;
  334. color f3 = #7A3E2A;
  335. color g3 = #A48137;
  336. color e2 = #97BBCB;
  337. color a4 = #3B4257;
  338. color b4 = #6A4345;
  339. color d4 = #86451F;
  340. color c4 = #345A48;
  341. color f4 = #A92F21;
  342. color g4 = #BC983B;
  343. color a5 = #3D4358;
  344. color b5 = #402623;
  345. color d5 = #85442D;
  346. color c5 = #3B403A;
  347. color f5 = #7A150B;
  348. color g5 = #252F2B;
  349. color a1 = #597099;
  350. color e4 = #0A3878;
  351. color b1 = #D16365;
  352. color d1 = #FFD43B;
  353. color c1 = #B7BF98;
  354. color e1 = #CAD2C8;
  355. color e0 = #F5EDE5;
  356. color f1 = #D17978;
  357. color g1 = #FDD23E;
  358. color a0 = #C5C3CC;
  359. color e3 = #0485B1;
  360. color b0 = #FFDCD6;
  361. color d0 = #FFE9BE;
  362. color c0 = #F0E9D5;
  363. color f0 = #E4C8BF;
  364. color g0 = #FBE6BA;
  365. color a2 = #3D4B79;
  366. color e5 = #084064;
  367. color b2 = #974244;
  368. color d2 = #F8AA08;
  369. color c2 = #4E937F;
  370. color f2 = #8F4330;
  371. color g2 = #FFDB03;
  372. color colors[][] = {
  373. {a0,a1,a2,a3,a4,a5},
  374. {b0,b1,b2,b3,b4,b5},
  375. {c0,c1,c2,c3,c4,c5},
  376. {d0,d1,d2,d3,d4,d5},
  377. {e0,e1,e2,e3,e4,e5},
  378. {f0,f1,f2,f3,f4,f5},
  379. {g0,g1,g2,g3,g4,g5}
  380. };
  381. class PrivacyLevel {
  382. public static int SECRET = 5; //passwords, keys etc.
  383. public static int PRIVATE = 4;//ssn etc, strict need to know basis stuff
  384. public static int INTIMATE = 3;//e.g. stuff you share with family
  385. public static int AFFILIATE = 2;//e.g. stuff you share with work, project etc
  386. public static int PUBLIC = 1;//e.g. stuff that everybody may know, your e.g. twitter handle
  387. public static int COMMONS = 0;//stuff that is intended for the public good / commons, anonimized IoT stuff
  388. }
  389. class ContextType {
  390. public static int SELF = 5; //stuff that applies strictly to yourself
  391. public static int FAMILY = 4;//stuff that applies to you and your family (hopefully not facebook pics)
  392. public static int FRIENDS = 3;//stuff you share with friends
  393. public static int WORK = 2;//stuff you share in a professional context
  394. public static int HOBBY = 1;//stuff you share in the context of a pastime
  395. public static int OTHER = 0;//stuff that doesn't fit in any of the other types
  396. }
  397. public int getColor(int privacy_level, int context_type)
  398. {
  399. return colors[context_type][privacy_level];
  400. }
  401. void draw(){
  402. size(100,100);
  403. background(0);
  404. noStroke();
  405. int level = PrivacyLevel.SECRET;
  406. int contextType = ContextType.SELF;
  407. color secret_self = getColor(level, contextType);//should be dark red
  408. fill(secret_self);
  409. ellipse(50,50,50,50);
  410. }
  411. </script> <canvas id="ob-e4084f25c6566c618f6cc091e4920fd86e9b1c21"></canvas>
  412. #+END_EXPORT
  413. #+name: color_example_src_2
  414. #+BEGIN_SRC java
  415. void draw(){
  416. size(100,100);
  417. background(0);
  418. noStroke();
  419. int level = PrivacyLevel.PUBLIC;
  420. int contextType = ContextType.WORK;
  421. color work_public = getColor(level, contextType);//expect light blueish
  422. fill(work_public);
  423. ellipse(50,50,50,50);
  424. }
  425. #+END_SRC
  426. #+name: color_example_2
  427. #+BEGIN_SRC processing :noweb yes
  428. <<colors>>
  429. <<color_example_src_2>>
  430. #+END_SRC
  431. #+RESULTS: color_example_2
  432. #+BEGIN_EXPORT html
  433. <script src="processing.js"></script>
  434. <script type="text/processing" data-processing-target="ob-760b680df1e803a95f5ec520fa92b091eca605c2">
  435. //color definitions
  436. color a3 = #3A3B58;
  437. color b3 = #734246;
  438. color d3 = #B4561F;
  439. color c3 = #336F60;
  440. color f3 = #7A3E2A;
  441. color g3 = #A48137;
  442. color e2 = #97BBCB;
  443. color a4 = #3B4257;
  444. color b4 = #6A4345;
  445. color d4 = #86451F;
  446. color c4 = #345A48;
  447. color f4 = #A92F21;
  448. color g4 = #BC983B;
  449. color a5 = #3D4358;
  450. color b5 = #402623;
  451. color d5 = #85442D;
  452. color c5 = #3B403A;
  453. color f5 = #7A150B;
  454. color g5 = #252F2B;
  455. color a1 = #597099;
  456. color e4 = #0A3878;
  457. color b1 = #D16365;
  458. color d1 = #FFD43B;
  459. color c1 = #B7BF98;
  460. color e1 = #CAD2C8;
  461. color e0 = #F5EDE5;
  462. color f1 = #D17978;
  463. color g1 = #FDD23E;
  464. color a0 = #C5C3CC;
  465. color e3 = #0485B1;
  466. color b0 = #FFDCD6;
  467. color d0 = #FFE9BE;
  468. color c0 = #F0E9D5;
  469. color f0 = #E4C8BF;
  470. color g0 = #FBE6BA;
  471. color a2 = #3D4B79;
  472. color e5 = #084064;
  473. color b2 = #974244;
  474. color d2 = #F8AA08;
  475. color c2 = #4E937F;
  476. color f2 = #8F4330;
  477. color g2 = #FFDB03;
  478. color colors[][] = {
  479. {a0,a1,a2,a3,a4,a5},
  480. {b0,b1,b2,b3,b4,b5},
  481. {c0,c1,c2,c3,c4,c5},
  482. {d0,d1,d2,d3,d4,d5},
  483. {e0,e1,e2,e3,e4,e5},
  484. {f0,f1,f2,f3,f4,f5},
  485. {g0,g1,g2,g3,g4,g5}
  486. };
  487. class PrivacyLevel {
  488. public static int SECRET = 5; //passwords, keys etc.
  489. public static int PRIVATE = 4;//ssn etc, strict need to know basis stuff
  490. public static int INTIMATE = 3;//e.g. stuff you share with family
  491. public static int AFFILIATE = 2;//e.g. stuff you share with work, project etc
  492. public static int PUBLIC = 1;//e.g. stuff that everybody may know, your e.g. twitter handle
  493. public static int COMMONS = 0;//stuff that is intended for the public good / commons, anonimized IoT stuff
  494. }
  495. class ContextType {
  496. public static int SELF = 5; //stuff that applies strictly to yourself
  497. public static int FAMILY = 4;//stuff that applies to you and your family (hopefully not facebook pics)
  498. public static int FRIENDS = 3;//stuff you share with friends
  499. public static int WORK = 2;//stuff you share in a professional context
  500. public static int HOBBY = 1;//stuff you share in the context of a pastime
  501. public static int OTHER = 0;//stuff that doesn't fit in any of the other types
  502. }
  503. public int getColor(int privacy_level, int context_type)
  504. {
  505. return colors[context_type][privacy_level];
  506. }
  507. void draw(){
  508. size(100,100);
  509. background(0);
  510. noStroke();
  511. int level = PrivacyLevel.PUBLIC;
  512. int contextType = ContextType.WORK;
  513. color secret_self = getColor(level, contextType);//should be light blueish
  514. fill(secret_self);
  515. ellipse(50,50,50,50);
  516. }
  517. </script> <canvas id="ob-760b680df1e803a95f5ec520fa92b091eca605c2"></canvas>
  518. #+END_EXPORT
  519. This table shows all colors for each context / privacy level combination.
  520. Find out does this make sense?
  521. #+name: color_table
  522. #+BEGIN_SRC processing :noweb yes
  523. <<colors>>
  524. String[] levels = ["commons", "public", "affiliate", "intimate", "private", "secret"];
  525. String[] contexts = ["other", "hobby", "work", "education", "health", "personal", "financial"];
  526. void draw()
  527. {
  528. size(600,480);
  529. float row_height = 50;
  530. float column_width = 80;
  531. fill(0);
  532. //draw privacy level headers
  533. for (int i = 0; i < levels.length; i++ ){
  534. text(levels[i], (i + 1) * column_width, row_height );
  535. }
  536. //draw context headers
  537. for (int j = 0; j < contexts.length; j++)
  538. {
  539. text(contexts[j], 20, (j+2) * row_height);
  540. }
  541. //draw colors
  542. for(int i = 0; i < levels.length; i++)
  543. {
  544. float x = 20 + (i + 1) * column_width;
  545. for(int j = 0; j < contexts.length; j++)
  546. {
  547. float y = (j + 2) * row_height;
  548. color c = getColor(i,j);
  549. fill(c);
  550. ellipse(x,y, 20, 20);
  551. }
  552. }
  553. }
  554. #+END_SRC
  555. #+RESULTS: color_table
  556. #+BEGIN_EXPORT html
  557. <script src="processing.js"></script>
  558. <script type="text/processing" data-processing-target="ob-3feae6cdb28b3ff8b917ba627a7683e61138c65c">
  559. //color definitions
  560. color a3 = #3A3B58;
  561. color b3 = #734246;
  562. color d3 = #B4561F;
  563. color c3 = #336F60;
  564. color f3 = #7A3E2A;
  565. color g3 = #A48137;
  566. color e2 = #97BBCB;
  567. color a4 = #3B4257;
  568. color b4 = #6A4345;
  569. color d4 = #86451F;
  570. color c4 = #345A48;
  571. color f4 = #A92F21;
  572. color g4 = #BC983B;
  573. color a5 = #3D4358;
  574. color b5 = #402623;
  575. color d5 = #85442D;
  576. color c5 = #3B403A;
  577. color f5 = #7A150B;
  578. color g5 = #252F2B;
  579. color a1 = #597099;
  580. color e4 = #0A3878;
  581. color b1 = #D16365;
  582. color d1 = #FFD43B;
  583. color c1 = #B7BF98;
  584. color e1 = #CAD2C8;
  585. color e0 = #F5EDE5;
  586. color f1 = #D17978;
  587. color g1 = #FDD23E;
  588. color a0 = #C5C3CC;
  589. color e3 = #0485B1;
  590. color b0 = #FFDCD6;
  591. color d0 = #FFE9BE;
  592. color c0 = #F0E9D5;
  593. color f0 = #E4C8BF;
  594. color g0 = #FBE6BA;
  595. color a2 = #3D4B79;
  596. color e5 = #084064;
  597. color b2 = #974244;
  598. color d2 = #F8AA08;
  599. color c2 = #4E937F;
  600. color f2 = #8F4330;
  601. color g2 = #FFDB03;
  602. color colors[][] = {
  603. {b0,b1,b2,b3,b4,b5},
  604. {c0,c1,c2,c3,c4,c5},
  605. {a0,a1,a2,a3,a4,a5},
  606. {d0,d1,d2,d3,d4,d5},
  607. {e0,e1,e2,e3,e4,e5},
  608. {f0,f1,f2,f3,f4,f5},
  609. {g0,g1,g2,g3,g4,g5}
  610. };
  611. class PrivacyLevel {
  612. public static int SECRET = 5;
  613. public static int PRIVATE = 4;
  614. public static int INTIMATE = 3;
  615. public static int AFFILIATE = 2;
  616. public static int PUBLIC = 1;
  617. public static int COMMONS = 0;
  618. }
  619. class ContextType {
  620. public static int FINANCIAL = 6;
  621. public static int PERSONAL = 5;
  622. public static int HEALTH = 4;
  623. public static int EDUCATION = 3;
  624. public static int WORK = 2;
  625. public static int HOBBY = 1;
  626. public static int OTHER = 0;
  627. }
  628. public int getColor(int privacy_level, int context_type)
  629. {
  630. return colors[context_type][privacy_level];
  631. }
  632. String[] levels = ["commons", "public", "affiliate", "intimate", "private", "secret"];
  633. String[] contexts = ["other", "hobby", "work", "education", "health", "personal", "financial"];
  634. void draw()
  635. {
  636. size(800,800);
  637. float x = 0;
  638. float y = 0;
  639. float row_height = 20;
  640. float column_width = 20;
  641. for (int i = 0; i < levels.length; i++ ){
  642. text(levels[i], (i + 1) * column_width );
  643. for (String context : contexts)
  644. {
  645. }
  646. }
  647. }
  648. </script> <canvas id="ob-3feae6cdb28b3ff8b917ba627a7683e61138c65c"></canvas>
  649. #+END_EXPORT
  650. #+name: glue
  651. #+BEGIN_SRC java :exports none
  652. class Request
  653. {
  654. public String application;
  655. public int contextType;
  656. public String[] required_properties;
  657. public String[] optional_properties;
  658. public Request(String app, int contextType, String[] req, String[] opt)
  659. {
  660. this.application = app;
  661. this.contextType = contextType;
  662. this.required_properties = req;
  663. this.optional_properties = opt;
  664. }
  665. }
  666. class Diff
  667. {
  668. public String context;
  669. public String[] intersect;
  670. public String[] except;
  671. public Diff(String ctx, String[] intersect, String[] except)
  672. {
  673. this.context = ctx;
  674. this.intersect = intersect;
  675. this.except = except;
  676. }
  677. }
  678. class Property
  679. {
  680. public String type;
  681. public String value;
  682. public int pl;//privacy level
  683. public Property(String type, String value, int pl)
  684. {
  685. this.type = type;
  686. this.value = value;
  687. this.pl = pl;
  688. }
  689. }
  690. class Context
  691. {
  692. public String title;
  693. public int plSum;
  694. public int contextType;
  695. public Property[] properties;
  696. public Context(String title, int plSum, int contextType, Property[] properties)
  697. {
  698. this.title = title;
  699. this.plSum = plSum;
  700. this.properties = properties;
  701. this.contextType = contextType;
  702. }
  703. }
  704. XMLElement doc = new XMLElement(this, 'diff.xml');
  705. //create typed versions because this is java :-(
  706. Request parseRequest(XMLElement xml)
  707. {
  708. XMLElement req = xml.getChild(0);
  709. String name = req.getChild(0).getContent();
  710. int contextType = req.getChild(1).getContent();
  711. String[] required = new String[req.getChild(2).getChildCount()];
  712. String[] optional = new String[req.getChild(3).getChildCount()];
  713. for (int i = 0; i < required.length; i++) {
  714. required[i] = req.getChild(2).getChild(i).getContent();
  715. }
  716. for (int i = 0; i < optional.length; i++) {
  717. optional[i] = req.getChild(3).getChild(i).getContent();
  718. }
  719. Request r = new Request(name,contextType,required,optional);
  720. return r;
  721. }
  722. Context[] parseProfile(XMLElement xml)
  723. {
  724. XMLElement profile = xml.getChild(2);
  725. Context[] contexts = new Context[profile.getChildCount()];
  726. for(int i = 0; i < contexts.length; i++)
  727. {
  728. String contextName = profile.getChild(i).getChild(0).getContent();
  729. int contextType = parseInt(profile.getChild(i).getChild(1).getContent());
  730. int plSum = parseInt(profile.getChild(i).getChild(2).getContent());
  731. XMLElement propertiesEl = profile.getChild(i).getChild(3);
  732. Property[] properties = new Property[propertiesEl.getChildCount()];
  733. for(int j = 0; j < properties.length; j++)
  734. {
  735. Property prop = parseProperty(propertiesEl.getChild(j));
  736. properties[j] = prop;
  737. }
  738. Context context = new Context(contextName, plSum, contextType, properties);
  739. contexts[i] = context;
  740. }
  741. return contexts;
  742. }
  743. Property parseProperty(XMLElement propertyEl)
  744. {
  745. String propertyType = propertyEl.getChild(0).getContent();
  746. String value = propertyEl.getChild(1).getContent();
  747. int pl = parseInt(propertyEl.getChild(2).getContent());
  748. return new Property(propertyType, value, pl);
  749. }
  750. //create typed versions because this is java :-(
  751. Diff[] parseDiffs(xml)
  752. {
  753. XMLElement diffsEl = xml.getChild(1);
  754. Diff[] diffs = new Diff[diffsEl.getChildCount()];
  755. for(int i = 0; i < diffs.length; i++)
  756. {
  757. String contextName = diffsEl.getChild(i).getChild(0).getContent();
  758. String[] intersects = new String[diffsEl.getChild(i).getChild(1).getChildCount()];
  759. String[] except = new String[diffsEl.getChild(i).getChild(2).getChildCount()];
  760. for(int j = 0; j < intersects.length; j++)
  761. {
  762. intersects[j] = diffsEl.getChild(i).getChild(1).getChild(j).getContent();
  763. }
  764. for(int j = 0; j < except.length; j++)
  765. {
  766. except[j] = diffsEl.getChild(i).getChild(2).getChild(j).getContent();
  767. }
  768. Diff diff = new Diff(contextName,intersects,except);
  769. diffs[i] = diff;
  770. }
  771. return diffs;
  772. }
  773. Request request = parseRequest(doc);
  774. Diff[] diffs = parseDiffs(doc);
  775. Context[] contexts = parseProfile(doc);
  776. #+END_SRC
  777. ** Request
  778. #+name: draw_request_src
  779. #+BEGIN_SRC java
  780. size(200,200);
  781. //background(0);
  782. noFill();
  783. //the size of request is fixed for now
  784. float centerX = width/2;
  785. float centerY = height/2;
  786. float rsize = 55;
  787. //color of request is mapped to the privacy type of the request, each request has one.
  788. color reqColor = getColor(PrivacyLevel.PUBLIC, request.contextType);
  789. fill(reqColor);
  790. ellipse(centerX, centerY, rsize, rsize);
  791. //show the name of the application that makes the request, centered below the circle
  792. fill(0);
  793. textAlign(CENTER,CENTER);
  794. text(request.application, centerX, centerY + rsize/1.5);
  795. #+END_SRC
  796. #+name: draw_request
  797. #+BEGIN_SRC processing :noweb yes
  798. <<colors>>
  799. <<glue>>
  800. <<draw_request_src>>
  801. #+END_SRC
  802. #+RESULTS: draw_request
  803. #+BEGIN_EXPORT html
  804. <script src="processing.js"></script>
  805. <script type="text/processing" data-processing-target="ob-7bacb312f1e57618d3a25d1d7df81deb408229ff">
  806. //color definitions
  807. color a3 = #3A3B58;
  808. color b3 = #734246;
  809. color d3 = #B4561F;
  810. color c3 = #336F60;
  811. color f3 = #7A3E2A;
  812. color g3 = #A48137;
  813. color e2 = #97BBCB;
  814. color a4 = #3B4257;
  815. color b4 = #6A4345;
  816. color d4 = #86451F;
  817. color c4 = #345A48;
  818. color f4 = #A92F21;
  819. color g4 = #BC983B;
  820. color a5 = #3D4358;
  821. color b5 = #402623;
  822. color d5 = #85442D;
  823. color c5 = #3B403A;
  824. color f5 = #7A150B;
  825. color g5 = #252F2B;
  826. color a1 = #597099;
  827. color e4 = #0A3878;
  828. color b1 = #D16365;
  829. color d1 = #FFD43B;
  830. color c1 = #B7BF98;
  831. color e1 = #CAD2C8;
  832. color e0 = #F5EDE5;
  833. color f1 = #D17978;
  834. color g1 = #FDD23E;
  835. color a0 = #C5C3CC;
  836. color e3 = #0485B1;
  837. color b0 = #FFDCD6;
  838. color d0 = #FFE9BE;
  839. color c0 = #F0E9D5;
  840. color f0 = #E4C8BF;
  841. color g0 = #FBE6BA;
  842. color a2 = #3D4B79;
  843. color e5 = #084064;
  844. color b2 = #974244;
  845. color d2 = #F8AA08;
  846. color c2 = #4E937F;
  847. color f2 = #8F4330;
  848. color g2 = #FFDB03;
  849. color colors[][] = {
  850. {b0,b1,b2,b3,b4,b5},
  851. {c0,c1,c2,c3,c4,c5},
  852. {a0,a1,a2,a3,a4,a5},
  853. {d0,d1,d2,d3,d4,d5},
  854. {e0,e1,e2,e3,e4,e5},
  855. {f0,f1,f2,f3,f4,f5},
  856. {g0,g1,g2,g3,g4,g5}
  857. };
  858. class PrivacyLevel {
  859. public static int SECRET = 5; //passwords, keys etc.
  860. public static int PRIVATE = 4;//ssn etc, strict need to know basis stuff
  861. public static int INTIMATE = 3;//e.g. stuff you share with family
  862. public static int AFFILIATE = 2;//e.g. stuff you share with work, project etc
  863. public static int PUBLIC = 1;//e.g. stuff that everybody may know, your e.g. twitter handle
  864. public static int COMMONS = 0;//stuff that is intended for the public good / commons, anonimized IoT stuff
  865. }
  866. class ContextType {
  867. public static int SELF = 5; //stuff that applies strictly to yourself
  868. public static int FAMILY = 4;//stuff that applies to you and your family (hopefully not facebook pics)
  869. public static int FRIENDS = 3;//stuff you share with friends
  870. public static int WORK = 2;//stuff you share in a professional context
  871. public static int HOBBY = 1;//stuff you share in the context of a pastime
  872. public static int OTHER = 0;//stuff that doesn't fit in any of the other types
  873. }
  874. public int getColor(int privacy_level, int context_type)
  875. {
  876. return colors[context_type][privacy_level];
  877. }
  878. class Request
  879. {
  880. public String application;
  881. public int contextType;
  882. public String[] required_properties;
  883. public String[] optional_properties;
  884. public Request(String app, int contextType, String[] req, String[] opt)
  885. {
  886. this.application = app;
  887. this.contextType = contextType;
  888. this.required_properties = req;
  889. this.optional_properties = opt;
  890. }
  891. }
  892. class Diff
  893. {
  894. public String context;
  895. public String[] intersect;
  896. public String[] except;
  897. public Diff(String ctx, String[] intersect, String[] except)
  898. {
  899. this.context = ctx;
  900. this.intersect = intersect;
  901. this.except = except;
  902. }
  903. }
  904. class Property
  905. {
  906. public String type;
  907. public String value;
  908. public int pl;//privacy level
  909. public Property(String type, String value, int pl)
  910. {
  911. this.type = type;
  912. this.value = value;
  913. this.pl = pl;
  914. }
  915. }
  916. class Context
  917. {
  918. public String title;
  919. public int plSum;
  920. public Property[] properties;
  921. public Context(String title, int plSum, Property[] properties)
  922. {
  923. this.title = title;
  924. this.plSum = plSum;
  925. this.properties = properties;
  926. }
  927. }
  928. XMLElement doc = new XMLElement(this, 'diff.xml');
  929. //create typed versions because this is java :-(
  930. Request parseRequest(XMLElement xml)
  931. {
  932. XMLElement req = xml.getChild(0);
  933. String name = req.getChild(0).getContent();
  934. int contextType = req.getChild(1).getContent();
  935. String[] required = new String[req.getChild(2).getChildCount()];
  936. String[] optional = new String[req.getChild(3).getChildCount()];
  937. for (int i = 0; i < required.length; i++) {
  938. required[i] = req.getChild(2).getChild(i).getContent();
  939. }
  940. for (int i = 0; i < optional.length; i++) {
  941. optional[i] = req.getChild(3).getChild(i).getContent();
  942. }
  943. Request r = new Request(name,contextType,required,optional);
  944. return r;
  945. }
  946. Context[] parseProfile(XMLElement xml)
  947. {
  948. XMLElement profile = xml.getChild(2);
  949. Context[] contexts = new Context[profile.getChildCount()];
  950. for(int i = 0; i < contexts.length; i++)
  951. {
  952. String contextName = profile.getChild(i).getChild(0).getContent();
  953. int plSum = parseInt(profile.getChild(i).getChild(1).getContent());
  954. XMLElement propertiesEl = profile.getChild(i).getChild(2);
  955. Property[] properties = new Property[propertiesEl.getChildCount()];
  956. for(int j = 0; j < properties.length; j++)
  957. {
  958. Property prop = parseProperty(propertiesEl.getChild(j));
  959. properties[j] = prop;
  960. }
  961. Context context = new Context(contextName, plSum, properties);
  962. contexts[i] = context;
  963. }
  964. return contexts;
  965. }
  966. Property parseProperty(XMLElement propertyEl)
  967. {
  968. String propertyType = propertyEl.getChild(0).getContent();
  969. String value = propertyEl.getChild(1).getContent();
  970. int pl = parseInt(propertyEl.getChild(2).getContent());
  971. return new Property(propertyType, value, pl);
  972. }
  973. //create typed versions because this is java :-(
  974. Diff[] parseDiffs(xml)
  975. {
  976. XMLElement diffsEl = xml.getChild(1);
  977. Diff[] diffs = new Diff[diffsEl.getChildCount()];
  978. for(int i = 0; i < diffs.length; i++)
  979. {
  980. String contextName = diffsEl.getChild(i).getChild(0).getContent();
  981. String[] intersects = new String[diffsEl.getChild(i).getChild(1).getChildCount()];
  982. String[] except = new String[diffsEl.getChild(i).getChild(2).getChildCount()];
  983. for(int j = 0; j < intersects.length; j++)
  984. {
  985. intersects[j] = diffsEl.getChild(i).getChild(1).getChild(j).getContent();
  986. }
  987. for(int j = 0; j < except.length; j++)
  988. {
  989. except[j] = diffsEl.getChild(i).getChild(2).getChild(j).getContent();
  990. }
  991. Diff diff = new Diff(contextName,intersects,except);
  992. diffs[i] = diff;
  993. }
  994. return diffs;
  995. }
  996. Request request = parseRequest(doc);
  997. Diff[] diffs = parseDiffs(doc);
  998. Context[] contexts = parseProfile(doc);
  999. size(200,200);
  1000. //background(0);
  1001. noFill();
  1002. stroke(255);
  1003. //the size of request is fixed for now
  1004. ffloat centerX = width/2;
  1005. float centerY = height/2;
  1006. float rsize = 55;
  1007. //color of request is mapped to the privacy type of the request, each request has one.
  1008. //INTIMATE because it's in the middle of the privacy level continuum
  1009. color reqColor = getColor(PrivacyLevel.INTIMATE, request.contextType);
  1010. fill(reqColor);
  1011. ellipse(centerX, centerY, rsize, rsize);
  1012. //show the name of the application that makes the request, centered below the circle
  1013. fill(0);
  1014. textAlign(CENTER,CENTER);
  1015. text("hoezo", centerX, centerY + rsize/1.5);
  1016. </script> <canvas id="ob-7bacb312f1e57618d3a25d1d7df81deb408229ff"></canvas>
  1017. #+END_EXPORT
  1018. ** Contexts
  1019. We want to draw each context in relation to the request,
  1020. so we place each context equidistant from the request in the center.
  1021. #+name: draw_context_src
  1022. #+BEGIN_SRC java
  1023. void setup(){
  1024. size(800,800);
  1025. smooth();
  1026. noLoop();
  1027. }
  1028. //divide the circle by the amount of contexts
  1029. //to get the angle between the lines that indicate the center of each context
  1030. float eqd_angle = TWO_PI / contexts.length;
  1031. void draw()
  1032. {
  1033. //TODO move draw request to a function
  1034. //the size of request is fixed for now
  1035. float centerX = width/2;
  1036. float centerY = height/2;
  1037. float rsize = 55;
  1038. //color of request is mapped to the privacy type of the request, each request has one.
  1039. color reqColor = getColor(PrivacyLevel.PUBLIC, request.contextType);
  1040. fill(reqColor);
  1041. ellipse(centerX, centerY, rsize, rsize);
  1042. //show the name of the application that makes the request, centered below the circle
  1043. fill(0);
  1044. textAlign(CENTER,CENTER);
  1045. text(request.application, centerX, centerY + rsize/1.5);
  1046. int count = 0;
  1047. for(Context context : contexts)
  1048. {
  1049. float angle = (count * eqd_angle) - (PI/2);//start drawing at the top
  1050. float distance = 200;//random(100,300);//random between 50 and 300
  1051. float csize = 100;//random(50,100); //random between 50 and 100
  1052. float x = centerX + distance * cos(angle); //calculate xPos
  1053. float y = centerY + distance * sin(angle); //calculate yPos
  1054. //each context should have a contextType too, in order to base the color on it.
  1055. color contextColor = getColor(PrivacyLevel.PUBLIC, context.contextType);
  1056. fill(contextColor);
  1057. ellipse(x, y, csize, csize);//fixed sizes and distances for now.
  1058. //show context label
  1059. fill(0);
  1060. textAlign(CENTER,CENTER);
  1061. text(context.title, x, y + csize/1.5);
  1062. count++;
  1063. }
  1064. }
  1065. #+END_SRC
  1066. #+name: draw_context
  1067. #+BEGIN_SRC processing :noweb yes
  1068. <<colors>>
  1069. <<glue>>
  1070. <<draw_context_src>>
  1071. #+END_SRC
  1072. #+RESULTS: draw_context
  1073. #+BEGIN_EXPORT html
  1074. <script src="processing.js"></script>
  1075. <script type="text/processing" data-processing-target="ob-c5ac3c4c54147ecffc2f4eea88af7cca0a1a2f6d">
  1076. class Request
  1077. {
  1078. public String application;
  1079. public String[] required_properties;
  1080. public String[] optional_properties;
  1081. public Request(String app, String[] req, String[] opt)
  1082. {
  1083. this.application = app;
  1084. this.required_properties = req;
  1085. this.optional_properties = opt;
  1086. }
  1087. }
  1088. class Diff
  1089. {
  1090. public String context;
  1091. public String[] intersect;
  1092. public String[] except;
  1093. public Diff(String ctx, String[] intersect, String[] except)
  1094. {
  1095. this.context = ctx;
  1096. this.intersect = intersect;
  1097. this.except = except;
  1098. }
  1099. }
  1100. //TODO: add Profile / Context / Property classes here
  1101. class Context
  1102. {
  1103. public String title;
  1104. public int plSum;
  1105. public Context(String title, int plSum)
  1106. {
  1107. this.title = title;
  1108. this.plSum = plSum;
  1109. }
  1110. }
  1111. XMLElement doc = new XMLElement(this, 'diff.xml');
  1112. //create typed versions because this is java :-(
  1113. Request parseRequest(xml)
  1114. {
  1115. XMLElement req = xml.getChild(0);
  1116. String name = req.getChild(0).getContent();
  1117. String[] required = new String[req.getChild(1).getChildCount()];
  1118. String[] optional = new String[req.getChild(2).getChildCount()];
  1119. for (int i = 0; i < required.length; i++) {
  1120. required[i] = req.getChild(1).getChild(i).getContent();
  1121. }
  1122. for (int i = 0; i < optional.length; i++) {
  1123. optional[i] = req.getChild(2).getChild(i).getContent();
  1124. }
  1125. Request r = new Request(name,required,optional);
  1126. return r;
  1127. }
  1128. Context[] parseProfile(xml)
  1129. {
  1130. //TODO: implement this! so that we can finally start on the real visualization
  1131. XMLElement profile = xml.getChild(2);
  1132. Context[] contexts = new Context[profile.getChildCount()];
  1133. for(int i = 0; i < contexts.length; i++)
  1134. {
  1135. String contextName = profile.getChild(i).getChild(0).getContent();
  1136. int plSum = profile.getChild(i).getChild(0).getContent();
  1137. Context context = new Context(contextName, plSum);
  1138. contexts[i] = context;
  1139. }
  1140. return contexts;
  1141. }
  1142. //create typed versions because this is java :-(
  1143. Diff[] parseDiffs(xml)
  1144. {
  1145. XMLElement diffsEl = xml.getChild(1);
  1146. Diff[] diffs = new Diff[diffsEl.getChildCount()];
  1147. for(int i = 0; i < diffs.length; i++)
  1148. {
  1149. String contextName = diffsEl.getChild(i).getChild(0).getContent();
  1150. String[] intersects = new String[diffsEl.getChild(i).getChild(1).getChildCount()];
  1151. String[] except = new String[diffsEl.getChild(i).getChild(2).getChildCount()];
  1152. for(int j = 0; j < intersects.length; j++)
  1153. {
  1154. intersects[j] = diffsEl.getChild(i).getChild(1).getChild(j).getContent();
  1155. }
  1156. for(int j = 0; j < except.length; j++)
  1157. {
  1158. except[j] = diffsEl.getChild(i).getChild(2).getChild(j).getContent();
  1159. }
  1160. Diff diff = new Diff(contextName,intersects,except);
  1161. diffs[i] = diff;
  1162. }
  1163. return diffs;
  1164. }
  1165. Request request = parseRequest(doc);
  1166. Diff[] diffs = parseDiffs(doc);
  1167. Context[] contexts = parseProfile(doc);
  1168. //draw the difference for each context with the request
  1169. size(200,200);
  1170. background(0);
  1171. noFill();
  1172. stroke(255);
  1173. ellipse(56, 46, 55, 55);
  1174. text(diffs[0].context, 10, 10);
  1175. </script> <canvas id="ob-c5ac3c4c54147ecffc2f4eea88af7cca0a1a2f6d"></canvas>
  1176. #+END_EXPORT
  1177. *** Things to further investigate
  1178. - How do we show relation between request and each context with color?
  1179. - Can we use distance as well as color to indicate the relation?
  1180. - Can we use size of the circle to indicate the weight, or use badges?
  1181. * Interaction
  1182. We intend to investigate this in Processing as well.
  1183. #+name: diff_interaction_src
  1184. #+BEGIN_SRC java
  1185. //divide the circle by the amount of contexts
  1186. //to get the angle between the lines that indicate the center of each context
  1187. float eqd_angle = TWO_PI / contexts.length;
  1188. //draw request circle in the center of the screen
  1189. float centerX, centerY;
  1190. float xOffset, yOffset;
  1191. float requestSize = 50;
  1192. //context parameters
  1193. float contextDistance = 200;//random(100,300);//random between 50 and 300
  1194. float contextSize = 100;//random(50,100); //random between 50 and 100
  1195. float requestX, requestY;//request coordinates, they can move
  1196. boolean hitRequest = false;
  1197. boolean dragging = false;
  1198. int hitContext = -1;//-1 if no context is hit, otherwise indicates the index of the hit context
  1199. void setup(){
  1200. size(800,800);
  1201. smooth();
  1202. //initialize screen when it is appropriate,
  1203. //before this it will display the wrong size
  1204. centerX = width/2;
  1205. centerY = height/2;
  1206. //request starts in the middle
  1207. requestX = centerX;
  1208. requestY = centerY;
  1209. }
  1210. //draw the request and label
  1211. void drawRequest()
  1212. {
  1213. color strokeColor = hitRequest? 255 : 153;
  1214. stroke(strokeColor);
  1215. color reqColor = getColor(PrivacyLevel.PUBLIC, request.contextType);
  1216. fill(reqColor);
  1217. ellipse(requestX,requestY, requestSize,requestSize);
  1218. fill(0);
  1219. textAlign(CENTER,CENTER);
  1220. text(request.application, requestX, requestY + 50/1.5);
  1221. //TODO: show weight of request
  1222. //text("" + weights[0], requestX, requestY);
  1223. }
  1224. //darken the given color, expects hsb color mode
  1225. int darken(int c)
  1226. {
  1227. float h = hue(c);
  1228. float s = saturation(c);
  1229. float v = brightness(c);
  1230. return color(h,s,v * 0.6);
  1231. }
  1232. void drawContexts()
  1233. {
  1234. //draw the contexts equidistant around the center where the request is
  1235. int count = 0;
  1236. for(String context : contexts)
  1237. {
  1238. float angle = (count * eqd_angle) - (PI/2);//start drawing at the top
  1239. float x = centerX + contextDistance * cos(angle); //calculate xPos
  1240. float y = centerY + contextDistance * sin(angle); //calculate yPos
  1241. color strokeColor = (hitContext == count) ? 255 : 153;
  1242. stroke(strokeColor);
  1243. color contextColor = getColor(PrivacyLevel.PUBLIC, context.contextType);
  1244. fill(contextColor);
  1245. ellipse(x, y, contextSize,contextSize);//fixed sizes and distances for now.
  1246. //show label
  1247. fill(0);
  1248. textAlign(CENTER,CENTER);
  1249. text(context.title, x, y + contextSize/1.5);
  1250. colorMode(HSB);
  1251. fill(darken(contextColor));
  1252. text("" + context.plSum, x, y);
  1253. colorMode(RGB);
  1254. count++;
  1255. }
  1256. }
  1257. //create a string that lists the values of the intersection in d, with the values in c
  1258. String getIntersection(Context c, Diff d)
  1259. {
  1260. String result = "";
  1261. for(String key : d.intersect)
  1262. {
  1263. String value = getPropertyValue(c, key);
  1264. if(value != null) result += key + " (" + value + ")\n";
  1265. }
  1266. return result;
  1267. }
  1268. //create a string that lists the missing keys in the intersection d
  1269. String getMissing(Diff d)
  1270. {
  1271. String result = "";
  1272. for(String key : d.except)
  1273. {
  1274. result += key + "\n";
  1275. }
  1276. return result;
  1277. }
  1278. //get the value of a property value in c designated by key
  1279. String getPropertyValue(Context c, String key)
  1280. {
  1281. for(Property p : c.properties)
  1282. {
  1283. if(p.type == key)
  1284. {
  1285. return p.value;
  1286. }
  1287. }
  1288. return null;
  1289. }
  1290. //show label
  1291. void drawDiff()
  1292. {
  1293. Context c = contexts[hitContext];
  1294. Diff d = diffs[hitContext];
  1295. String available = getIntersection(c,d);
  1296. String missing = getMissing(d);
  1297. String diffMessage = "RELEASE TO ENTITLE: \n" + available + "\nSTILL MISSING: \n" + missing;
  1298. fill(0);
  1299. textAlign(CENTER,CENTER);
  1300. text(diffMessage, centerX, centerY);
  1301. }
  1302. void draw()
  1303. {
  1304. //clear bg
  1305. background(200);
  1306. //draw hitbox
  1307. float originX = requestX - requestSize/2;
  1308. float originY = requestY - requestSize/2;
  1309. //rect(originX,originY, requestSize, requestSize);
  1310. //test if cursor is over the hitbox
  1311. hitRequest = (mouseX > originX && mouseX < (originX + requestSize) &&
  1312. mouseY > originY && mouseY < (originY + requestSize));
  1313. drawContexts();
  1314. drawRequest();//on top
  1315. //String debug_info = "mx: " + mouseX + ", my: " + mouseY + ", ox: " + originX + ", oy: " + originY;
  1316. //text(debug_info, mouseX, mouseY);
  1317. if(hitContext > -1)
  1318. {
  1319. //show diff information
  1320. drawDiff();
  1321. }
  1322. }
  1323. void mousePressed() {
  1324. dragging = hitRequest;
  1325. xOffset = mouseX - requestX;
  1326. yOffset = mouseY - requestY;
  1327. }
  1328. void mouseDragged()
  1329. {
  1330. if(dragging)
  1331. {
  1332. requestX = mouseX - xOffset;
  1333. requestY = mouseY - yOffset;
  1334. int contextWasHit = -1;
  1335. for(int i = 0; i < contexts.length; i++)
  1336. {
  1337. float angle = (i * eqd_angle) - (PI/2);
  1338. float x = centerX + contextDistance * cos(angle);
  1339. float y = centerY + contextDistance * sin(angle);
  1340. boolean hit = (mouseX > x - contextSize/2 && mouseX < x + contextSize/2
  1341. && mouseY > y - contextSize/2 && mouseY < y + contextSize/2);
  1342. if(hit) contextWasHit = i;
  1343. }
  1344. hitContext = contextWasHit;
  1345. }
  1346. }
  1347. void mouseReleased()
  1348. {
  1349. dragging = false;
  1350. hitContext = -1;
  1351. requestX = centerX;
  1352. requestY = centerY;
  1353. }
  1354. #+END_SRC
  1355. #+name: diff_interaction
  1356. #+BEGIN_SRC processing :noweb yes
  1357. <<colors>>
  1358. <<glue>>
  1359. <<diff_interaction_src>>
  1360. #+END_SRC
  1361. #+RESULTS:
  1362. #+BEGIN_EXPORT html
  1363. <script src="processing.js"></script>
  1364. <script type="text/processing" data-processing-target="ob-6bc863022fc27d931ab179e8a556a1cda07821fc">
  1365. //color definitions
  1366. color a3 = #3A3B58;
  1367. color b3 = #734246;
  1368. color d3 = #B4561F;
  1369. color c3 = #336F60;
  1370. color f3 = #7A3E2A;
  1371. color g3 = #A48137;
  1372. color e2 = #97BBCB;
  1373. color a4 = #3B4257;
  1374. color b4 = #6A4345;
  1375. color d4 = #86451F;
  1376. color c4 = #345A48;
  1377. color f4 = #A92F21;
  1378. color g4 = #BC983B;
  1379. color a5 = #3D4358;
  1380. color b5 = #402623;
  1381. color d5 = #85442D;
  1382. color c5 = #3B403A;
  1383. color f5 = #7A150B;
  1384. color g5 = #252F2B;
  1385. color a1 = #597099;
  1386. color e4 = #0A3878;
  1387. color b1 = #D16365;
  1388. color d1 = #FFD43B;
  1389. color c1 = #B7BF98;
  1390. color e1 = #CAD2C8;
  1391. color e0 = #F5EDE5;
  1392. color f1 = #D17978;
  1393. color g1 = #FDD23E;
  1394. color a0 = #C5C3CC;
  1395. color e3 = #0485B1;
  1396. color b0 = #FFDCD6;
  1397. color d0 = #FFE9BE;
  1398. color c0 = #F0E9D5;
  1399. color f0 = #E4C8BF;
  1400. color g0 = #FBE6BA;
  1401. color a2 = #3D4B79;
  1402. color e5 = #084064;
  1403. color b2 = #974244;
  1404. color d2 = #F8AA08;
  1405. color c2 = #4E937F;
  1406. color f2 = #8F4330;
  1407. color g2 = #FFDB03;
  1408. color colors[][] = {
  1409. {b0,b1,b2,b3,b4,b5},
  1410. {c0,c1,c2,c3,c4,c5},
  1411. {a0,a1,a2,a3,a4,a5},
  1412. {d0,d1,d2,d3,d4,d5},
  1413. {e0,e1,e2,e3,e4,e5},
  1414. {f0,f1,f2,f3,f4,f5},
  1415. {g0,g1,g2,g3,g4,g5}
  1416. };
  1417. class PrivacyLevel {
  1418. public static int SECRET = 5;
  1419. public static int PRIVATE = 4;
  1420. public static int INTIMATE = 3;
  1421. public static int AFFILIATE = 2;
  1422. public static int PUBLIC = 1;
  1423. public static int COMMONS = 0;
  1424. }
  1425. class ContextType {
  1426. public static int FINANCIAL = 6;
  1427. public static int PERSONAL = 5;
  1428. public static int HEALTH = 4;
  1429. public static int EDUCATION = 3;
  1430. public static int WORK = 2;
  1431. public static int HOBBY = 1;
  1432. public static int OTHER = 0;
  1433. }
  1434. public int getColor(int privacy_level, int context_type)
  1435. {
  1436. return colors[context_type][privacy_level];
  1437. }
  1438. class Request
  1439. {
  1440. public String application;
  1441. public int contextType;
  1442. public String[] required_properties;
  1443. public String[] optional_properties;
  1444. public Request(String app, int contextType, String[] req, String[] opt)
  1445. {
  1446. this.application = app;
  1447. this.contextType = contextType;
  1448. this.required_properties = req;
  1449. this.optional_properties = opt;
  1450. }
  1451. }
  1452. class Diff
  1453. {
  1454. public String context;
  1455. public String[] intersect;
  1456. public String[] except;
  1457. public Diff(String ctx, String[] intersect, String[] except)
  1458. {
  1459. this.context = ctx;
  1460. this.intersect = intersect;
  1461. this.except = except;
  1462. }
  1463. }
  1464. class Property
  1465. {
  1466. public String type;
  1467. public String value;
  1468. public int pl;//privacy level
  1469. public Property(String type, String value, int pl)
  1470. {
  1471. this.type = type;
  1472. this.value = value;
  1473. this.pl = pl;
  1474. }
  1475. }
  1476. class Context
  1477. {
  1478. public String title;
  1479. public int plSum;
  1480. public int contextType;
  1481. public Property[] properties;
  1482. public Context(String title, int plSum, int contextType, Property[] properties)
  1483. {
  1484. this.title = title;
  1485. this.plSum = plSum;
  1486. this.properties = properties;
  1487. this.contextType = contextType;
  1488. }
  1489. }
  1490. XMLElement doc = new XMLElement(this, 'diff.xml');
  1491. //create typed versions because this is java :-(
  1492. Request parseRequest(XMLElement xml)
  1493. {
  1494. XMLElement req = xml.getChild(0);
  1495. String name = req.getChild(0).getContent();
  1496. int contextType = req.getChild(1).getContent();
  1497. String[] required = new String[req.getChild(2).getChildCount()];
  1498. String[] optional = new String[req.getChild(3).getChildCount()];
  1499. for (int i = 0; i < required.length; i++) {
  1500. required[i] = req.getChild(2).getChild(i).getContent();
  1501. }
  1502. for (int i = 0; i < optional.length; i++) {
  1503. optional[i] = req.getChild(3).getChild(i).getContent();
  1504. }
  1505. Request r = new Request(name,contextType,required,optional);
  1506. return r;
  1507. }
  1508. Context[] parseProfile(XMLElement xml)
  1509. {
  1510. XMLElement profile = xml.getChild(2);
  1511. Context[] contexts = new Context[profile.getChildCount()];
  1512. for(int i = 0; i < contexts.length; i++)
  1513. {
  1514. String contextName = profile.getChild(i).getChild(0).getContent();
  1515. int contextType = parseInt(profile.getChild(i).getChild(1).getContent());
  1516. int plSum = parseInt(profile.getChild(i).getChild(2).getContent());
  1517. XMLElement propertiesEl = profile.getChild(i).getChild(3);
  1518. Property[] properties = new Property[propertiesEl.getChildCount()];
  1519. for(int j = 0; j < properties.length; j++)
  1520. {
  1521. Property prop = parseProperty(propertiesEl.getChild(j));
  1522. properties[j] = prop;
  1523. }
  1524. Context context = new Context(contextName, plSum, contextType, properties);
  1525. contexts[i] = context;
  1526. }
  1527. return contexts;
  1528. }
  1529. Property parseProperty(XMLElement propertyEl)
  1530. {
  1531. String propertyType = propertyEl.getChild(0).getContent();
  1532. String value = propertyEl.getChild(1).getContent();
  1533. int pl = parseInt(propertyEl.getChild(2).getContent());
  1534. return new Property(propertyType, value, pl);
  1535. }
  1536. //create typed versions because this is java :-(
  1537. Diff[] parseDiffs(xml)
  1538. {
  1539. XMLElement diffsEl = xml.getChild(1);
  1540. Diff[] diffs = new Diff[diffsEl.getChildCount()];
  1541. for(int i = 0; i < diffs.length; i++)
  1542. {
  1543. String contextName = diffsEl.getChild(i).getChild(0).getContent();
  1544. String[] intersects = new String[diffsEl.getChild(i).getChild(1).getChildCount()];
  1545. String[] except = new String[diffsEl.getChild(i).getChild(2).getChildCount()];
  1546. for(int j = 0; j < intersects.length; j++)
  1547. {
  1548. intersects[j] = diffsEl.getChild(i).getChild(1).getChild(j).getContent();
  1549. }
  1550. for(int j = 0; j < except.length; j++)
  1551. {
  1552. except[j] = diffsEl.getChild(i).getChild(2).getChild(j).getContent();
  1553. }
  1554. Diff diff = new Diff(contextName,intersects,except);
  1555. diffs[i] = diff;
  1556. }
  1557. return diffs;
  1558. }
  1559. Request request = parseRequest(doc);
  1560. Diff[] diffs = parseDiffs(doc);
  1561. Context[] contexts = parseProfile(doc);
  1562. //divide the circle by the amount of contexts
  1563. //to get the angle between the lines that indicate the center of each context
  1564. float eqd_angle = TWO_PI / contexts.length;
  1565. //draw request circle in the center of the screen
  1566. float centerX, centerY;
  1567. float xOffset, yOffset;
  1568. float requestSize = 50;
  1569. //context parameters
  1570. float contextDistance = 200;//random(100,300);//random between 50 and 300
  1571. float contextSize = 100;//random(50,100); //random between 50 and 100
  1572. float requestX, requestY;//request coordinates, they can move
  1573. boolean hitRequest = false;
  1574. boolean dragging = false;
  1575. int hitContext = -1;//-1 if no context is hit, otherwise indicates the index of the hit context
  1576. void setup(){
  1577. size(800,800);
  1578. smooth();
  1579. //initialize screen when it is appropriate,
  1580. //before this it will display the wrong size
  1581. centerX = width/2;
  1582. centerY = height/2;
  1583. //request starts in the middle
  1584. requestX = centerX;
  1585. requestY = centerY;
  1586. }
  1587. //draw the request and label
  1588. void drawRequest()
  1589. {
  1590. color strokeColor = hitRequest? 255 : 153;
  1591. stroke(strokeColor);
  1592. color reqColor = getColor(PrivacyLevel.PUBLIC, request.contextType);
  1593. fill(reqColor);
  1594. ellipse(requestX,requestY, requestSize,requestSize);
  1595. fill(0);
  1596. textAlign(CENTER,CENTER);
  1597. text(request.application, requestX, requestY + 50/1.5);
  1598. //TODO: show weight of request
  1599. //text("" + weights[0], requestX, requestY);
  1600. }
  1601. //darken the given color, expects hsb color mode
  1602. int darken(int c)
  1603. {
  1604. float h = hue(c);
  1605. float s = saturation(c);
  1606. float v = brightness(c);
  1607. return color(h,s,v * 0.6);
  1608. }
  1609. void drawContexts()
  1610. {
  1611. //draw the contexts equidistant around the center where the request is
  1612. int count = 0;
  1613. for(String context : contexts)
  1614. {
  1615. float angle = (count * eqd_angle) - (PI/2);//start drawing at the top
  1616. float x = centerX + contextDistance * cos(angle); //calculate xPos
  1617. float y = centerY + contextDistance * sin(angle); //calculate yPos
  1618. color strokeColor = (hitContext == count) ? 255 : 153;
  1619. stroke(strokeColor);
  1620. color contextColor = getColor(PrivacyLevel.PUBLIC, context.contextType);
  1621. fill(contextColor);
  1622. ellipse(x, y, contextSize,contextSize);//fixed sizes and distances for now.
  1623. //show label
  1624. fill(0);
  1625. textAlign(CENTER,CENTER);
  1626. text(context.title, x, y + contextSize/1.5);
  1627. colorMode(HSB);
  1628. fill(darken(contextColor));
  1629. text("" + context.plSum, x, y);
  1630. colorMode(RGB);
  1631. count++;
  1632. }
  1633. }
  1634. //show label
  1635. void drawDiff()
  1636. {
  1637. fill(0);
  1638. textAlign(CENTER,CENTER);
  1639. text("RELEASE TO ENTITLE:\nname (Taco van Dijk)\n email(taco@waag.org)\n address(spaarndammerdijk 194)\n\n STILL MISSING:\n phone", centerX, centerY);
  1640. }
  1641. void draw()
  1642. {
  1643. //clear bg
  1644. background(200);
  1645. //draw hitbox
  1646. float originX = requestX - requestSize/2;
  1647. float originY = requestY - requestSize/2;
  1648. rect(originX,originY, requestSize, requestSize);
  1649. //draw debug info
  1650. String debug_info = "mouseX: " + mouseX + "mouseY: " + mouseY;
  1651. text(debug_info, mouseX, mouseY);
  1652. //test if cursor is over the hitbox
  1653. hitRequest = (mouseX > originX && mouseX < (originX + requestSize) &&
  1654. mouseY > originY && mouseY < (originY + requestSize));
  1655. drawContexts();
  1656. drawRequest();//on top
  1657. if(hitContext > -1)
  1658. {
  1659. //show diff information
  1660. drawDiff();
  1661. }
  1662. }
  1663. void mousePressed() {
  1664. dragging = hitRequest;
  1665. xOffset = mouseX - requestX;
  1666. yOffset = mouseY - requestY;
  1667. }
  1668. void mouseDragged()
  1669. {
  1670. if(dragging)
  1671. {
  1672. requestX = mouseX - xOffset;
  1673. requestY = mouseY - yOffset;
  1674. int contextWasHit = -1;
  1675. for(int i = 0; i < contexts.length; i++)
  1676. {
  1677. float angle = (i * eqd_angle) - (PI/2);
  1678. float x = centerX + contextDistance * cos(angle);
  1679. float y = centerY + contextDistance * sin(angle);
  1680. boolean hit = (mouseX > x - contextSize/2 && mouseX < x + contextSize/2
  1681. && mouseY > y - contextSize/2 && mouseY < y + contextSize/2);
  1682. if(hit) contextWasHit = i;
  1683. }
  1684. hitContext = contextWasHit;
  1685. }
  1686. }
  1687. void mouseReleased()
  1688. {
  1689. dragging = false;
  1690. hitContext = -1;
  1691. requestX = centerX;
  1692. requestY = centerY;
  1693. }
  1694. </script> <canvas id="ob-6bc863022fc27d931ab179e8a556a1cda07821fc"></canvas>
  1695. #+END_EXPORT
  1696. *** Things to further investigate
  1697. - How does the end user actually accept the request? Is it by dragging the request onto the context?
  1698. - How does the end user decline the request?