wads 0.1.1 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/wads.rb CHANGED
@@ -4,4 +4,4 @@ require_relative "wads/version"
4
4
  require_relative "wads/data_structures"
5
5
  require_relative "wads/widgets"
6
6
  require_relative "wads/textinput"
7
-
7
+ require_relative "wads/app"
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
data/run-graph ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+
3
+ ruby samples/graph.rb
data/run-star-wars ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+
3
+ ruby samples/star_wars.rb
data/run-stocks ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+
3
+ ruby samples/stocks.rb
data/run-theme-test ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+
3
+ ruby samples/theme_test.rb $1 $2 $3
@@ -0,0 +1,66 @@
1
+ require 'gosu'
2
+ require_relative '../lib/wads'
3
+
4
+ include Wads
5
+ #
6
+ # The WadsApp class provides a simple starting point to quickly build a native
7
+ # Ruby application using Gosu as an underlying library. It provides all the necessary
8
+ # hooks to get started. All you need to do is supply the parent Wads widget using
9
+ # the set_display(widget) method. See one of the Wads samples for example usage.
10
+ #
11
+ class BasicGosuAppWithGraph < Gosu::Window
12
+ def initialize
13
+ super(800, 600)
14
+ self.caption = 'Basic Gosu App with Graph Widget'
15
+ @font = Gosu::Font.new(22)
16
+ @graph_widget = GraphWidget.new(10, 110, # x, y coordinate of top left corder
17
+ 780, 480, # width x height
18
+ create_graph,
19
+ GRAPH_DISPLAY_EXPLORER)
20
+ @update_count = 0
21
+ end
22
+
23
+ def create_graph
24
+ g = Graph.new
25
+ g.add("A")
26
+ g.add("B")
27
+ g.add("C")
28
+ g.add("D")
29
+ g.add("E")
30
+ g.add("F")
31
+ g.connect("A", "B")
32
+ g.connect("A", "C")
33
+ g.connect("B", "D")
34
+ g.connect("B", "E")
35
+ g.connect("E", "F")
36
+ g
37
+ end
38
+
39
+ def update
40
+ # Calling handle_update on the grpah widget is required if you want interactivity
41
+ # specifically, for drag and drop of the nodes
42
+ @update_count = @update_count + 1
43
+ @graph_widget.handle_update @update_count, mouse_x, mouse_y
44
+ end
45
+
46
+ def draw
47
+ @font.draw_text("Sample App with Wads Graph Widget", 240, 49, 1, 1, 1, COLOR_WHITE)
48
+ @graph_widget.draw
49
+ end
50
+
51
+ def button_down id
52
+ close if id == Gosu::KbEscape
53
+ # Delegate button events to the graph widget if you want the
54
+ # user to be able to interact with it
55
+ @graph_widget.button_down id, mouse_x, mouse_y
56
+ end
57
+
58
+ def button_up id
59
+ # Delegate button events to the graph widget if you want the
60
+ # user to be able to interact with it
61
+ @graph_widget.button_up id, mouse_x, mouse_y
62
+ end
63
+ end
64
+
65
+
66
+ BasicGosuAppWithGraph.new.show
data/samples/graph.rb ADDED
@@ -0,0 +1,72 @@
1
+ require 'gosu'
2
+ require_relative '../lib/wads'
3
+
4
+ include Wads
5
+
6
+ class SampleGraphApp < WadsApp
7
+
8
+ SAMPLE_GRAPH_DEFINITION_FILE = "./data/sample_graph.csv"
9
+
10
+ def initialize
11
+ super(800, 600, "Wads Sample Graph App", GraphDisplay.new(create_sample_graph))
12
+ end
13
+
14
+ #
15
+ # Below are three different ways you can construct a graph
16
+ #
17
+ def create_sample_graph
18
+ g = Graph.new
19
+ g.add("A")
20
+ g.add("B")
21
+ g.add("C")
22
+ g.add("D")
23
+ g.add("E")
24
+ g.add("F")
25
+ g.connect("A", "B")
26
+ g.connect("A", "C")
27
+ g.connect("B", "D")
28
+ g.connect("B", "E")
29
+ g.connect("E", "F")
30
+ g
31
+ end
32
+
33
+ def create_sample_graph_using_nodes
34
+ root = Node.new("A")
35
+ b = root.add("B")
36
+ b.add("D")
37
+ b.add("E").add("F")
38
+ root.add("C")
39
+ Graph.new(root)
40
+ end
41
+
42
+ def create_sample_graph_from_file
43
+ Graph.new(SAMPLE_GRAPH_DEFINITION_FILE)
44
+ end
45
+ end
46
+
47
+ class GraphDisplay < Widget
48
+
49
+ def initialize(graph)
50
+ super(0, 0, 800, 600)
51
+ set_layout(LAYOUT_TOP_MIDDLE_BOTTOM)
52
+ @graph = graph
53
+
54
+ image = get_layout.add_image("./media/Banner.png", { ARG_SECTION => SECTION_TOP})
55
+ image.add_text("Wads Sample App", 10, 20, nil, true)
56
+ image.add_text("Version #{Wads::VERSION}", 13, 54)
57
+
58
+ panel = get_layout.add_horizontal_panel({ ARG_SECTION => SECTION_BOTTOM})
59
+ panel.add_button("Exit", 0, panel.height - 30) do
60
+ WidgetResult.new(true)
61
+ end
62
+ panel.center_children
63
+ panel.disable_border
64
+
65
+ @graph_display = get_layout.add_graph_display(@graph, GRAPH_DISPLAY_EXPLORER,
66
+ { ARG_SECTION => SECTION_CENTER})
67
+ disable_border
68
+ end
69
+ end
70
+
71
+ #WadsConfig.instance.set_current_theme(WadsNoIconTheme.new)
72
+ SampleGraphApp.new.show
@@ -0,0 +1,112 @@
1
+ require 'gosu'
2
+ require 'json'
3
+ require_relative '../lib/wads'
4
+
5
+ include Wads
6
+
7
+ class SampleStarWarsApp < WadsApp
8
+
9
+ STAR_WARS_DATA_FILE = "./data/starwars-episode-4-interactions.json"
10
+
11
+ def initialize
12
+ super(800, 800, "Wads Sample Star Wars App", StarWarsDisplay.new(process_star_wars_data))
13
+ end
14
+
15
+ def process_star_wars_data
16
+ star_wars_json = File.read(STAR_WARS_DATA_FILE)
17
+ data_hash = JSON.parse(star_wars_json)
18
+ characters = data_hash['nodes']
19
+ interactions = data_hash['links']
20
+
21
+ # The interactions in the data set reference the characters by their
22
+ # zero based index, so we keep a reference in our graph by index.
23
+ # The character's value is the number of scenes in which they appear.
24
+ graph = Graph.new
25
+ characters.each do |character|
26
+ node_tags = {}
27
+ node_color_str = character['colour']
28
+ # This is a bit of a hack, but our background is black so black text
29
+ # will not show up. Change this to white
30
+ if node_color_str == "#000000"
31
+ node_color_str = "#FFFFFF"
32
+ end
33
+ # Convert hex string (ex. "#EE00AA") into int hex representation
34
+ # understood by Gosu color (ex. 0xFFEE00AA)
35
+ node_color = "0xFF#{node_color_str[1..-1]}".to_i(16)
36
+ node_tags['color'] = node_color
37
+ graph.add_node(Node.new(character['name'], character['value'], node_tags))
38
+ end
39
+ interactions.each do |interaction|
40
+ character_one = graph.node_by_index(interaction['source'])
41
+ character_two = graph.node_by_index(interaction['target'])
42
+ number_of_scenes_together = interaction['value']
43
+ edge_tags = {}
44
+ edge_tags["scenes"] = number_of_scenes_together
45
+ graph.add_edge(character_one, character_two, edge_tags)
46
+ end
47
+ graph
48
+ end
49
+ end
50
+
51
+ class StarWarsDisplay < Widget
52
+ attr_accessor :graph
53
+
54
+ def initialize(graph)
55
+ super(0, 0, 800, 800)
56
+ set_layout(LAYOUT_TOP_MIDDLE_BOTTOM)
57
+ @graph = graph
58
+
59
+ image = get_layout.add_image("./media/Banner.png", { ARG_SECTION => SECTION_TOP})
60
+ image.add_text("Wads Sample App", 10, 20, nil, true)
61
+ image.add_text("Version #{Wads::VERSION}", 13, 54)
62
+
63
+ get_layout.add_document(sample_content, { ARG_SECTION => SECTION_CENTER})
64
+
65
+ panel = get_layout.add_horizontal_panel({ ARG_SECTION => SECTION_BOTTOM})
66
+ panel.add_button("Exit", 0, panel.height - 30) do
67
+ WidgetResult.new(true)
68
+ end
69
+ panel.center_children
70
+ panel.disable_border
71
+
72
+ @data_table = get_layout.add_single_select_table(
73
+ ["Character", "Number of Scenes"], 4, { ARG_SECTION => SECTION_CENTER})
74
+
75
+ @graph.node_list.each do |character|
76
+ @data_table.add_row([character.name, character.value], character.get_tag(ARG_COLOR))
77
+ end
78
+ @graph_display = get_layout.add_graph_display(@graph, GRAPH_DISPLAY_EXPLORER,
79
+ { ARG_SECTION => SECTION_CENTER})
80
+
81
+ disable_border
82
+ end
83
+
84
+ def sample_content
85
+ <<~HEREDOC
86
+ This sample analysis shows the interactions between characters in the Star Wars
87
+ Episode 4: A New Hope. Click on a character to see more detail.
88
+ HEREDOC
89
+ end
90
+
91
+ def handle_key_press id, mouse_x, mouse_y
92
+ if id == Gosu::KbUp
93
+ @data_table.scroll_up
94
+ elsif id == Gosu::KbDown
95
+ @data_table.scroll_down
96
+ end
97
+ WidgetResult.new(false)
98
+ end
99
+
100
+ def handle_mouse_down mouse_x, mouse_y
101
+ if @data_table.contains_click(mouse_x, mouse_y)
102
+ val = @data_table.set_selected_row(mouse_y, 0)
103
+ if not val.nil?
104
+ node = @graph.find_node(val)
105
+ #@graph_display.set_center_node(node, 2)
106
+ @graph_display.set_explorer_display(node)
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ SampleStarWarsApp.new.show
data/samples/stocks.rb ADDED
@@ -0,0 +1,126 @@
1
+ require 'gosu'
2
+ require_relative '../lib/wads'
3
+
4
+ include Wads
5
+
6
+ class SampleStocksApp < WadsApp
7
+
8
+ STOCKS_DATA_FILE = "./data/NASDAQ.csv"
9
+
10
+ def initialize
11
+ super(800, 600, "Wads Sample Stocks App", StocksDisplay.new(process_stock_data))
12
+ end
13
+
14
+ def process_stock_data
15
+ # The data file comes from https://finance.yahoo.com
16
+ # The format of this file is as follows:
17
+ #
18
+ # Date,Open,High,Low,Close,Adj Close,Volume
19
+ # 2000-01-03,4186.189941,4192.189941,3989.709961,4131.149902,4131.149902,1510070000
20
+ # 2000-01-04,4020.000000,4073.250000,3898.229980,3901.689941,3901.689941,1511840000
21
+ # ...
22
+ # 2020-12-30,12906.509766,12924.929688,12857.759766,12870.000000,12870.000000,5292210000
23
+ # 2020-12-31,12877.089844,12902.070313,12821.230469,12888.280273,12888.280273,4771390000
24
+
25
+ stats = Stats.new("NASDAQ")
26
+ previous_close = nil
27
+
28
+ puts "Read the data file #{STOCKS_DATA_FILE}"
29
+ File.readlines(STOCKS_DATA_FILE).each do |line|
30
+ line = line.chomp # remove the carriage return
31
+
32
+ # Ignore header and any empty lines, process numeric data lines
33
+ if line.length > 0 and line[0].match(/[0-9]/)
34
+ values = line.split(",")
35
+ date = Date.strptime(values[0], "%Y-%m-%d")
36
+ weekday = Date::DAYNAMES[date.wday]
37
+
38
+ open_value = values[1].to_f
39
+ close_value = values[4].to_f
40
+
41
+ if previous_close.nil?
42
+ # Just use the first day to set the baseline
43
+ previous_close = close_value
44
+ else
45
+ change_from_previous_close = close_value - previous_close
46
+ change_intraday = close_value - open_value
47
+ change_overnight = open_value - previous_close
48
+
49
+ change_percent = change_from_previous_close / previous_close
50
+
51
+ stats.add(weekday, change_percent)
52
+ stats.add("#{weekday} prev close", change_from_previous_close)
53
+ stats.add("#{weekday} intraday", change_intraday)
54
+ stats.add("#{weekday} overnight", change_overnight)
55
+
56
+ previous_close = close_value
57
+ end
58
+ end
59
+ end
60
+
61
+ stats
62
+ end
63
+ end
64
+
65
+ class StocksDisplay < Widget
66
+
67
+ def initialize(stats)
68
+ super(0, 0, 800, 600)
69
+ set_layout(LAYOUT_TOP_MIDDLE_BOTTOM)
70
+
71
+ image = get_layout.add_image("./media/Banner.png", { ARG_SECTION => SECTION_TOP})
72
+ image.add_text("Wads Sample App", 10, 20, nil, true)
73
+ image.add_text("Version #{Wads::VERSION}", 13, 54)
74
+
75
+ get_layout.add_document(sample_content, { ARG_SECTION => SECTION_CENTER})
76
+
77
+ panel = get_layout.add_horizontal_panel({ ARG_SECTION => SECTION_BOTTOM})
78
+ panel.add_button("Exit", 0, panel.height - 30) do
79
+ WidgetResult.new(true)
80
+ end
81
+ panel.center_children
82
+
83
+ @data_table = get_layout.add_single_select_table(
84
+ ["Day", "Min", "Avg", "StdDev", "Max", "p10", "p90"], 5,
85
+ { ARG_SECTION => SECTION_CENTER})
86
+ Date::DAYNAMES[1..5].each do |day|
87
+ min = format_percent(stats.min(day))
88
+ avg = format_percent(stats.average(day))
89
+ std = format_percent(stats.std_dev(day))
90
+ max = format_percent(stats.max(day))
91
+ p10 = format_percent(stats.percentile(day, 0.1))
92
+ p90 = format_percent(stats.percentile(day, 0.90))
93
+ @data_table.add_row([day, min, avg, std, max, p10, p90])
94
+ end
95
+
96
+ @selection_text = nil
97
+ end
98
+
99
+ def format_percent(val)
100
+ "#{(val * 100).round(3)}%"
101
+ end
102
+
103
+ def sample_content
104
+ <<~HEREDOC
105
+ This sample stock analysis uses NASDAQ data from https://finance.yahoo.com looking
106
+ at closing data through the years 2000 to 2020. The percent gain or loss is broken
107
+ down per day, as shown in the table below.
108
+ HEREDOC
109
+ end
110
+
111
+ def render
112
+ @selection_text.draw unless @selection_text.nil?
113
+ end
114
+
115
+ def handle_mouse_down mouse_x, mouse_y
116
+ if @data_table.contains_click(mouse_x, mouse_y)
117
+ val = @data_table.set_selected_row(mouse_y, 0)
118
+ if not val.nil?
119
+ @selection_text = Text.new(relative_x(5), relative_y(500), "You selected #{val}, a great day!")
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ WadsConfig.instance.set_current_theme(WadsBrightTheme.new)
126
+ SampleStocksApp.new.show