MINT-core 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/.gemtest +0 -0
  2. data/Gemfile +17 -0
  3. data/Gemfile.lock +69 -0
  4. data/History.txt +3 -0
  5. data/MINT-core.gemspec +58 -0
  6. data/Manifest.txt +77 -0
  7. data/PostInstall.txt +7 -0
  8. data/README.rdoc +63 -0
  9. data/Rakefile +29 -0
  10. data/bin/mint-aui +40 -0
  11. data/bin/mint-cui-gfx +47 -0
  12. data/bin/mint-juggernaut.sh +4 -0
  13. data/bin/mint-tuplespace +12 -0
  14. data/lib/MINT-core.rb +42 -0
  15. data/lib/MINT-core/agent/agent.rb +28 -0
  16. data/lib/MINT-core/agent/aui.rb +52 -0
  17. data/lib/MINT-core/agent/auicontrol.rb +135 -0
  18. data/lib/MINT-core/agent/cui-gfx.rb +160 -0
  19. data/lib/MINT-core/agent/cuicontrol.rb +46 -0
  20. data/lib/MINT-core/mapping/complementary.rb +100 -0
  21. data/lib/MINT-core/mapping/mapping.rb +47 -0
  22. data/lib/MINT-core/mapping/on_state_change.rb +65 -0
  23. data/lib/MINT-core/mapping/sequential.rb +87 -0
  24. data/lib/MINT-core/model/aui/AIC.rb +86 -0
  25. data/lib/MINT-core/model/aui/AIChoice.rb +65 -0
  26. data/lib/MINT-core/model/aui/AIINChoose.rb +54 -0
  27. data/lib/MINT-core/model/aui/AIMultiChoice.rb +5 -0
  28. data/lib/MINT-core/model/aui/AIMultiChoiceElement.rb +56 -0
  29. data/lib/MINT-core/model/aui/AIO.rb +170 -0
  30. data/lib/MINT-core/model/aui/AIOUTDiscrete.rb +43 -0
  31. data/lib/MINT-core/model/aui/AISingleChoice.rb +9 -0
  32. data/lib/MINT-core/model/aui/AISingleChoiceElement.rb +69 -0
  33. data/lib/MINT-core/model/aui/AISinglePresence.rb +100 -0
  34. data/lib/MINT-core/model/aui/aic.png +0 -0
  35. data/lib/MINT-core/model/aui/aic.scxml +50 -0
  36. data/lib/MINT-core/model/aui/aichoice.png +0 -0
  37. data/lib/MINT-core/model/aui/aichoice.scxml +60 -0
  38. data/lib/MINT-core/model/aui/aio.png +0 -0
  39. data/lib/MINT-core/model/aui/aio.scxml +43 -0
  40. data/lib/MINT-core/model/aui/aisinglechoiceelement.png +0 -0
  41. data/lib/MINT-core/model/aui/aisinglechoiceelement.scxml +71 -0
  42. data/lib/MINT-core/model/aui/aisinglepresence.png +0 -0
  43. data/lib/MINT-core/model/aui/aisinglepresence.scxml +58 -0
  44. data/lib/MINT-core/model/aui/model.rb +50 -0
  45. data/lib/MINT-core/model/body/gesture_button.rb +26 -0
  46. data/lib/MINT-core/model/body/handgesture.rb +279 -0
  47. data/lib/MINT-core/model/body/head.png +0 -0
  48. data/lib/MINT-core/model/body/head.rb +51 -0
  49. data/lib/MINT-core/model/body/head.scxml +28 -0
  50. data/lib/MINT-core/model/cui/gfx/CIC.rb +266 -0
  51. data/lib/MINT-core/model/cui/gfx/CIO.rb +381 -0
  52. data/lib/MINT-core/model/cui/gfx/model.rb +204 -0
  53. data/lib/MINT-core/model/cui/gfx/screen.rb +18 -0
  54. data/lib/MINT-core/model/device/button.rb +20 -0
  55. data/lib/MINT-core/model/device/joypad.rb +30 -0
  56. data/lib/MINT-core/model/device/mouse.rb +171 -0
  57. data/lib/MINT-core/model/device/pointer.rb +85 -0
  58. data/lib/MINT-core/model/device/wheel.rb +51 -0
  59. data/lib/MINT-core/model/interactor.rb +167 -0
  60. data/lib/MINT-core/model/task.rb +71 -0
  61. data/lib/MINT-core/overrides/rinda.rb +34 -0
  62. data/script/console +10 -0
  63. data/script/destroy +14 -0
  64. data/script/generate +14 -0
  65. data/spec/AIC_spec.rb +69 -0
  66. data/spec/AISinglePresence_spec.rb +94 -0
  67. data/spec/MINT-core_spec.rb +11 -0
  68. data/spec/aio_agent_spec.rb +234 -0
  69. data/spec/aio_spec.rb +144 -0
  70. data/spec/aisinglechoice_spec.rb +152 -0
  71. data/spec/aisinglechoiceelement_spec.rb +106 -0
  72. data/spec/cio_spec.rb +369 -0
  73. data/spec/core_spec.rb +29 -0
  74. data/spec/music_spec.rb +179 -0
  75. data/spec/rcov.opts +2 -0
  76. data/spec/spec.opts +4 -0
  77. data/spec/spec_helper.rb +7 -0
  78. data/tasks/rspec.rake +21 -0
  79. metadata +227 -0
data/lib/MINT-core.rb ADDED
@@ -0,0 +1,42 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ module MINTCore
5
+ VERSION = '1.0.0'
6
+ end
7
+
8
+ require 'rubygems'
9
+ require "bundler/setup"
10
+ require 'statemachine'
11
+ require "cassowary"
12
+ require 'RMagick'
13
+ require "rinda/tuplespace"
14
+ require 'drb/drb'
15
+ require 'dm-core'
16
+ require 'dm-types'
17
+ require "MINT-scxml"
18
+
19
+ require "MINT-core/agent/agent"
20
+ require "MINT-core/mapping/mapping"
21
+ require "MINT-core/mapping/on_state_change"
22
+ require "MINT-core/mapping/complementary"
23
+ require "MINT-core/mapping/sequential"
24
+
25
+ require "MINT-core/model/interactor"
26
+ require "MINT-core/model/task"
27
+ require "MINT-core/agent/auicontrol"
28
+ require "MINT-core/agent/aui"
29
+ require "MINT-core/agent/cuicontrol"
30
+ require "MINT-core/agent/cui-gfx"
31
+ require "MINT-core/model/aui/model"
32
+ require "MINT-core/model/cui/gfx/model"
33
+
34
+ require "MINT-core/model/device/pointer"
35
+ require "MINT-core/model/device/button"
36
+ require "MINT-core/model/device/wheel"
37
+ require "MINT-core/model/device/joypad"
38
+ require "MINT-core/model/device/mouse"
39
+
40
+ require "MINT-core/model/body/gesture_button"
41
+ require "MINT-core/model/body/handgesture"
42
+ require "MINT-core/model/body/head"
@@ -0,0 +1,28 @@
1
+
2
+ module MINT
3
+ class Agent
4
+ attr_reader :running_mappings
5
+
6
+ def initialize(connection_options = { :adapter => "rinda", :host =>"localhost",:port=>4000})
7
+ DataMapper.setup(:default, connection_options)
8
+ DRb.start_service
9
+ @running_mappings = []
10
+ # DataMapper::Logger.new("data.log", :debug)
11
+ end
12
+
13
+ def addMapping(mapping)
14
+ m = mapping.execute
15
+
16
+ if not m.is_a? Array
17
+ m= [m]
18
+ end
19
+ @running_mappings += m
20
+ end
21
+
22
+ def run
23
+ @running_mappings.each do |thread|
24
+ thread.join
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,52 @@
1
+
2
+
3
+ module DataMapper
4
+ class Collection
5
+ def each
6
+ super do |resource|
7
+ begin
8
+ # original, resource.collection = resource.collection, self
9
+ yield resource
10
+ ensure
11
+ # resource.collection = original
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ class AUIAgent < MINT::Agent
19
+ include AUIControl
20
+
21
+ def initialize
22
+ super
23
+ end
24
+
25
+ def initial_calculation(result)
26
+
27
+ current_screen = Screen.first_or_create(:name => "current_screen")
28
+ current_screen.process_event(:calculate)
29
+
30
+ pts = InteractionTask.all(:abstract_states => /running/).map &:name
31
+ p "Initial Layout recalculation requested for new PTS #{pts.inspect} "
32
+
33
+ root = AUIControl.find_common(pts)
34
+
35
+ #layer=0
36
+ # remove all layoutements
37
+ # Layoutelement.all.destroy
38
+ mask = AIO.first(:name=>root)
39
+ AUIControl.organize2(mask)
40
+
41
+ # mask=composeScreen(root,true,layer)
42
+ mask.save
43
+
44
+ current_screen.update(:root=>root) # BUG/??w thereafter no iteration in calculateMinimumSizes is possible???
45
+ current_screen.process_event(:done)
46
+ p "finished: AUI root>#{root}"
47
+ end
48
+
49
+ end
50
+ # DataMapper::Logger.new("log/datamapper.log", :debug)
51
+
52
+
@@ -0,0 +1,135 @@
1
+
2
+ module AUIControl
3
+ include MINT
4
+
5
+ # ensures that all prev/next relationships are setup properlyin one complete sequence
6
+ def AUIControl.organize(aio,parent_aio = nil, layer = 0)
7
+
8
+ if (aio.kind_of? AIC)
9
+ aio.entry = aio.childs[0]
10
+ last = aio
11
+ aio.childs.each do |child|
12
+ last.next = child
13
+ child.previous = last
14
+
15
+ last = organize(child,aio,layer+1)
16
+ end
17
+ aio.process_event("organize")
18
+ return last
19
+ else
20
+ aio.process_event("organize")
21
+ return aio
22
+ end
23
+ end
24
+
25
+ # connects all aios on the same level
26
+ def AUIControl.organize2(aio,parent_aio = nil, layer = 0)
27
+ # if layer == 0
28
+ # aio.next = aio
29
+ # aio.previous = aio
30
+ # end
31
+
32
+ if (aio.kind_of? AIC)
33
+ first = aio.childs.first
34
+ last = nil
35
+
36
+ aio.childs.each do |child|
37
+ if last
38
+ last.next = child
39
+ end
40
+ child.previous = last
41
+ copy = child
42
+ organize2(copy,nil,layer+1)
43
+ last = child
44
+ end
45
+ aio.process_event!("organize")
46
+ else
47
+ aio.process_event!("organize")
48
+ end
49
+ p "organized #{aio.name}"
50
+ end
51
+
52
+ # Searches for the common root aic that contains all tasks of {elements}.
53
+ # During the search towards the root it activates all relevant containters in the
54
+ # {Layout}model in case {activate} is set to true.
55
+ #
56
+ # @param tasks [String} an array of strings of task names
57
+ # @param activate [Boolean] defines if all common comtainers should be activated
58
+ # @return [String] name of common root aic
59
+ #
60
+ def AUIControl.find_common_aic(tasks,activate=false, parents ={ })
61
+
62
+ if tasks.length==1
63
+ return tasks[0]
64
+ end
65
+
66
+ tasks.each do |e|
67
+ p "processing #{e}"
68
+ aio = AIO.first(:name=>e)
69
+ if (aio==nil)
70
+ throw ("AIO with name #{e} not found in AUI model!")
71
+ end
72
+ if (activate)
73
+ aio.process_event("present")
74
+ end
75
+ if aio.parent and not parents[aio.parent.name]
76
+ parents[aio.parent.name]=aio.name
77
+ elsif aio.parent and parents[aio.parent.name]
78
+ # already existing parent, thus all further saved parents of this task needs to be removed
79
+ puts "parents #{parents.inspect}"
80
+ parents.each {|k,v|
81
+ if (v.eql? parents[aio.parent.name] or v.eql? aio.name)
82
+ parents.delete(k)
83
+ p "delete key #{k} value #{v}"
84
+ end
85
+ }
86
+ parents[aio.parent.name]=aio.name
87
+ # parents.delete(parents.invert[ parents[aio.parent.name]])
88
+ end
89
+ end
90
+
91
+ p "next step"
92
+ if parents.length>0
93
+ return find_common_aic(parents.keys,activate,parents)
94
+ else
95
+ return tasks.first
96
+ end
97
+ end
98
+
99
+ def AUIControl.find_common(tasks)
100
+
101
+ if tasks.length==1
102
+ return tasks[0]
103
+ end
104
+
105
+ parents ={ }
106
+
107
+ tasks.each do |name|
108
+ t = AIO.first(:name=>name)
109
+ tname = t.name
110
+ parents[tname] = [tname]
111
+
112
+ while (t.parent)
113
+ parents[tname].push t.parent.name
114
+ t = t.parent
115
+ end
116
+ end
117
+
118
+ lasttaskname = nil
119
+ while 1==1
120
+ taskname = nil
121
+ parents.keys.each_with_index do |k,i|
122
+ if (i==0)
123
+ taskname = parents[k].pop
124
+ else
125
+ comp = parents[k].pop
126
+ if not comp.eql? taskname
127
+ return lasttaskname
128
+ end
129
+ end
130
+ end
131
+ lasttaskname = taskname
132
+ end
133
+ end
134
+ end
135
+
@@ -0,0 +1,160 @@
1
+
2
+ class LayoutAgent < MINT::Agent
3
+
4
+ include CUIControl
5
+
6
+ def initialize
7
+ @solver = Cassowary::ClSimplexSolver.new
8
+ super
9
+ end
10
+
11
+ def initial_calculation(result)
12
+ p "Initial Layout recalculation requested for new PTS #{result.inspect} "
13
+
14
+ #MINT::CIO.all.each { |c|
15
+ # c.calculateMinimumSize
16
+ # }
17
+
18
+
19
+ root_cio = CIO.first(:name=>result.root)
20
+
21
+
22
+ # p "#{root_le} root:#{root}"
23
+ #p "minimumspace = "+ calculateMinimumSquareSpace(root_le).to_s
24
+
25
+ #calculateOptSquareSpace(result.root, 800*600, 10)
26
+
27
+ root_cio.print
28
+ # pts = result.interactionTasks.map &:name
29
+ #root = find_common_container(pts,true)
30
+ # c = Box.new(:name=>le.name, :x=>0,:y=>0, :width=>1200, :height=>800, :layer=>1)
31
+ # c.save
32
+
33
+ root_cio.calculate_container(@solver,20)
34
+
35
+ CUIControl.fill_active_cio_cache
36
+
37
+ end
38
+
39
+
40
+ def calculate_layout_on_task_change(result)
41
+ p "Layout agent has recieved task removal request #{result.inspect}"
42
+
43
+ deactivate_layout_on_task_deactivate(result.name)
44
+ p "after task deaktivate"
45
+ root = find_container_to_recalculate(result.name)
46
+ c = Box.first(:name=>root)
47
+ setup_constraints(c)
48
+ end
49
+ #private
50
+
51
+ # @param [String] taskname name of container
52
+ # @return [String] container name to recalculate
53
+
54
+ def find_container_to_recalculate(taskname)
55
+ le = Layout.first(:name=>taskname)
56
+
57
+ if le.state.eql?("inactive")
58
+ # luis = Layout.all(:parent=>le.parent).map &:task
59
+ # luis.each do |name|
60
+ # cui = CUI.first(:task=>name)
61
+ # if (cui != nil)
62
+ # cui.destroy!
63
+ # end
64
+ # end
65
+ find_container_to_recalculate(le.layout)
66
+ else
67
+ #p "Container to recalculate #{le.inspect}"
68
+ return le.name
69
+ end
70
+ end
71
+
72
+ def calculateMinimumSquareSpace(le)
73
+ if le.type=="layoutcontainer"
74
+ # p "Calculating space for container #{le.name}"
75
+ space = 0
76
+
77
+ le.layoutelements.each do |e|
78
+ space = space + calculateMinimumSquareSpace(e)
79
+
80
+ end
81
+ # p "Calculated from container #{space}"
82
+ le.update(:minspace => space)
83
+
84
+
85
+ return space
86
+ else
87
+ # p "Calculating space for element #{le.inspect}"
88
+ if (le.minwidth and le.minheight)
89
+ space = le.minwidth*le.minheight
90
+ le.update(:minspace => space)
91
+ # p "calculated from element #{space}"
92
+ return space
93
+ else
94
+ return 0
95
+ end
96
+ end
97
+ end
98
+
99
+ def calculateOptSquareSpace(root_container, available_space,border)
100
+ root_le=Layoutelement.first(:name=>root_container)
101
+ min_space_used = root_le.minspace
102
+ quota = Float(available_space )/Float( min_space_used)
103
+ # p "quota: #{quota}"
104
+ calc_opt_square_traverse(quota, root_le,border)
105
+ end
106
+
107
+ def calc_opt_square_traverse(quota, root_le,border)
108
+ max_space = root_le.minspace*quota
109
+ kantenlaenge = Math.sqrt(max_space)
110
+ border_space = 4 * border * kantenlaenge - (2 * border)**2
111
+ optspace = root_le.minspace*quota-border_space
112
+ # p "Optspace for #{root_le.name} = #{optspace}"
113
+ root_le.update(:optspace => optspace)
114
+
115
+ if root_le.type=="layoutcontainer"
116
+ root_le.layoutelements.each do |e|
117
+ calc_opt_square_traverse(quota,e,border)
118
+ end
119
+ end
120
+ end
121
+
122
+ def wait_border_crossing(result)
123
+ p "subscribing to pointer #{result.parent.inspect}"
124
+
125
+ cio = CIO.first(:name=>result.parent.name)
126
+
127
+ p "got #{cio.inspect}"
128
+ Thread.new(cio.name,cio.x,cio.y,cio.width,cio.height) { |name,cx,cy,cw,ch|
129
+
130
+ Redis.new.subscribe("juggernaut") do |on|
131
+ on.message do |c,msg|
132
+ r = JSON.parse(msg)
133
+ if (r["channels"].include? "pointer")
134
+ if /POS/.match(r["data"])
135
+ z,x,y = /POS-(\d+),(\d+)/.match(r["data"]).to_a.map &:to_i
136
+ p "data #{x},#{y} #{cx} #{cy} #{cw} #{ch}"
137
+
138
+ if (x<cx or x>(cx+cw) or y<cy or y>(cy+ch))
139
+ p "outside!!!"
140
+
141
+ # Hacks start here
142
+
143
+ aio = AIO.first(:name=>"0")
144
+ aio.process_event(:suspend)
145
+
146
+ arframe = AIO.first(:name=>"ar_frame")
147
+ arframe.process_event(:present)
148
+ p "after"
149
+
150
+ Thread.stop
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ }
158
+ end
159
+
160
+ end
@@ -0,0 +1,46 @@
1
+ module CUIControl
2
+ include MINT
3
+
4
+ @active_cios = nil
5
+
6
+ def CUIControl.find_cio_from_coordinates(result)
7
+ puts "mouse stopped #{result.inspect}"
8
+ if result == nil or @active_cios == nil # we have not finished cui poition calculation, but we already received a mouse stopped event
9
+ return
10
+ end
11
+ x = result.x
12
+ y = result.y
13
+
14
+ highlighted_cio = CIO.first(:abstract_states=>/highlighted/)
15
+
16
+ if (highlighted_cio!=nil && highlighted_cio.x<=x && highlighted_cio.y<=y && highlighted_cio.x+highlighted_cio.width>=x && highlighted_cio.y+highlighted_cio.height>=y)
17
+ puts "unchanged"
18
+ return
19
+ else
20
+ found = @active_cios.select{ |e| e.x <=x && e.y<=y && e.x+e.width>=x && e.y+e.height>=y}
21
+
22
+ puts "found #{found.inspect}"
23
+
24
+ if (highlighted_cio)
25
+ highlighted_cio.process_event("unhighlight") # old focus
26
+ puts "unhighlight:"+highlighted_cio.name
27
+ # @highlighted_cio.update(:state=>"calculated") # old focus
28
+ end
29
+
30
+ if (found.first)
31
+ highlighted_cio = CIO.first(:name=>found.first.name)
32
+ highlighted_cio.process_event("highlight")
33
+ puts "highlighted:"+highlighted_cio.name
34
+ else
35
+ puts "no highlight"
36
+ return
37
+ end
38
+ end
39
+ end
40
+
41
+ def CUIControl.fill_active_cio_cache(result=nil)
42
+ @active_cios = CIO.all.select{ |e| e.is_in?(:presenting) and not e.kind_of? MINT::CIC }
43
+ puts "CIO cache initialized with #{@active_cios.length} elements"
44
+ end
45
+
46
+ end