MINT-core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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