hyper-operation 0.5.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.
- checksums.yaml +7 -0
- data/.gitignore +49 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +324 -0
- data/LICENSE.txt +21 -0
- data/README.md +708 -0
- data/Rakefile +4 -0
- data/examples/chat-app/.gitignore +21 -0
- data/examples/chat-app/Gemfile +57 -0
- data/examples/chat-app/Gemfile.lock +282 -0
- data/examples/chat-app/README.md +3 -0
- data/examples/chat-app/Rakefile +6 -0
- data/examples/chat-app/app/assets/config/manifest.js +3 -0
- data/examples/chat-app/app/assets/images/.keep +0 -0
- data/examples/chat-app/app/assets/javascripts/application.js +3 -0
- data/examples/chat-app/app/assets/javascripts/cable.js +13 -0
- data/examples/chat-app/app/assets/javascripts/channels/.keep +0 -0
- data/examples/chat-app/app/assets/stylesheets/application.css +15 -0
- data/examples/chat-app/app/channels/application_cable/channel.rb +4 -0
- data/examples/chat-app/app/channels/application_cable/connection.rb +4 -0
- data/examples/chat-app/app/controllers/application_controller.rb +3 -0
- data/examples/chat-app/app/controllers/concerns/.keep +0 -0
- data/examples/chat-app/app/controllers/home_controller.rb +5 -0
- data/examples/chat-app/app/helpers/application_helper.rb +2 -0
- data/examples/chat-app/app/hyperloop/components/app.rb +11 -0
- data/examples/chat-app/app/hyperloop/components/formatted_div.rb +13 -0
- data/examples/chat-app/app/hyperloop/components/input_box.rb +29 -0
- data/examples/chat-app/app/hyperloop/components/message.rb +29 -0
- data/examples/chat-app/app/hyperloop/components/messages.rb +9 -0
- data/examples/chat-app/app/hyperloop/components/nav.rb +30 -0
- data/examples/chat-app/app/hyperloop/operations/operations.rb +56 -0
- data/examples/chat-app/app/hyperloop/stores/message_store.rb +23 -0
- data/examples/chat-app/app/models/application_record.rb +3 -0
- data/examples/chat-app/app/models/concerns/.keep +0 -0
- data/examples/chat-app/app/models/models.rb +2 -0
- data/examples/chat-app/app/models/public/.keep +0 -0
- data/examples/chat-app/app/models/public/announcement.rb +8 -0
- data/examples/chat-app/app/policies/application_policy.rb +5 -0
- data/examples/chat-app/app/views/layouts/application.html.erb +51 -0
- data/examples/chat-app/bin/bundle +3 -0
- data/examples/chat-app/bin/rails +9 -0
- data/examples/chat-app/bin/rake +9 -0
- data/examples/chat-app/bin/setup +34 -0
- data/examples/chat-app/bin/spring +17 -0
- data/examples/chat-app/bin/update +29 -0
- data/examples/chat-app/config.ru +5 -0
- data/examples/chat-app/config/application.rb +13 -0
- data/examples/chat-app/config/boot.rb +3 -0
- data/examples/chat-app/config/cable.yml +9 -0
- data/examples/chat-app/config/database.yml +25 -0
- data/examples/chat-app/config/environment.rb +5 -0
- data/examples/chat-app/config/environments/development.rb +56 -0
- data/examples/chat-app/config/environments/production.rb +86 -0
- data/examples/chat-app/config/environments/test.rb +42 -0
- data/examples/chat-app/config/initializers/application_controller_renderer.rb +6 -0
- data/examples/chat-app/config/initializers/assets.rb +11 -0
- data/examples/chat-app/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/chat-app/config/initializers/cookies_serializer.rb +5 -0
- data/examples/chat-app/config/initializers/filter_parameter_logging.rb +4 -0
- data/examples/chat-app/config/initializers/hyperloop.rb +4 -0
- data/examples/chat-app/config/initializers/inflections.rb +16 -0
- data/examples/chat-app/config/initializers/mime_types.rb +4 -0
- data/examples/chat-app/config/initializers/new_framework_defaults.rb +24 -0
- data/examples/chat-app/config/initializers/session_store.rb +3 -0
- data/examples/chat-app/config/initializers/wrap_parameters.rb +14 -0
- data/examples/chat-app/config/locales/en.yml +23 -0
- data/examples/chat-app/config/puma.rb +47 -0
- data/examples/chat-app/config/routes.rb +5 -0
- data/examples/chat-app/config/secrets.yml +22 -0
- data/examples/chat-app/config/spring.rb +6 -0
- data/examples/chat-app/db/seeds.rb +7 -0
- data/examples/chat-app/lib/assets/.keep +0 -0
- data/examples/chat-app/lib/tasks/.keep +0 -0
- data/examples/chat-app/log/.keep +0 -0
- data/examples/chat-app/public/404.html +67 -0
- data/examples/chat-app/public/422.html +67 -0
- data/examples/chat-app/public/500.html +66 -0
- data/examples/chat-app/public/apple-touch-icon-precomposed.png +0 -0
- data/examples/chat-app/public/apple-touch-icon.png +0 -0
- data/examples/chat-app/public/favicon.ico +0 -0
- data/examples/chat-app/public/robots.txt +5 -0
- data/examples/chat-app/test/controllers/.keep +0 -0
- data/examples/chat-app/test/fixtures/.keep +0 -0
- data/examples/chat-app/test/fixtures/files/.keep +0 -0
- data/examples/chat-app/test/helpers/.keep +0 -0
- data/examples/chat-app/test/integration/.keep +0 -0
- data/examples/chat-app/test/mailers/.keep +0 -0
- data/examples/chat-app/test/models/.keep +0 -0
- data/examples/chat-app/test/test_helper.rb +10 -0
- data/examples/chat-app/tmp/.keep +0 -0
- data/examples/chat-app/vendor/assets/javascripts/.keep +0 -0
- data/examples/chat-app/vendor/assets/stylesheets/.keep +0 -0
- data/examples/five-letter-word-game/.gitignore +21 -0
- data/examples/five-letter-word-game/Gemfile +57 -0
- data/examples/five-letter-word-game/Gemfile.lock +282 -0
- data/examples/five-letter-word-game/README.md +24 -0
- data/examples/five-letter-word-game/Rakefile +6 -0
- data/examples/five-letter-word-game/app/assets/config/manifest.js +3 -0
- data/examples/five-letter-word-game/app/assets/images/.keep +0 -0
- data/examples/five-letter-word-game/app/assets/javascripts/application.js +3 -0
- data/examples/five-letter-word-game/app/assets/javascripts/cable.js +13 -0
- data/examples/five-letter-word-game/app/assets/javascripts/channels/.keep +0 -0
- data/examples/five-letter-word-game/app/assets/stylesheets/application.css +15 -0
- data/examples/five-letter-word-game/app/channels/application_cable/channel.rb +4 -0
- data/examples/five-letter-word-game/app/channels/application_cable/connection.rb +4 -0
- data/examples/five-letter-word-game/app/controllers/application_controller.rb +14 -0
- data/examples/five-letter-word-game/app/controllers/concerns/.keep +0 -0
- data/examples/five-letter-word-game/app/controllers/home_controller.rb +5 -0
- data/examples/five-letter-word-game/app/helpers/application_helper.rb +2 -0
- data/examples/five-letter-word-game/app/hyperloop/components/app.rb +65 -0
- data/examples/five-letter-word-game/app/hyperloop/components/guesses.rb +8 -0
- data/examples/five-letter-word-game/app/hyperloop/components/input_word.rb +13 -0
- data/examples/five-letter-word-game/app/hyperloop/models/user.rb +27 -0
- data/examples/five-letter-word-game/app/hyperloop/operations/ops.rb +115 -0
- data/examples/five-letter-word-game/app/hyperloop/stores/store.rb +120 -0
- data/examples/five-letter-word-game/app/jobs/application_job.rb +2 -0
- data/examples/five-letter-word-game/app/mailers/application_mailer.rb +4 -0
- data/examples/five-letter-word-game/app/models/application_record.rb +3 -0
- data/examples/five-letter-word-game/app/models/concerns/.keep +0 -0
- data/examples/five-letter-word-game/app/policies/user_policy.rb +4 -0
- data/examples/five-letter-word-game/app/views/layouts/application.html.erb +14 -0
- data/examples/five-letter-word-game/app/views/layouts/mailer.html.erb +13 -0
- data/examples/five-letter-word-game/app/views/layouts/mailer.text.erb +1 -0
- data/examples/five-letter-word-game/bin/bundle +3 -0
- data/examples/five-letter-word-game/bin/rails +9 -0
- data/examples/five-letter-word-game/bin/rake +9 -0
- data/examples/five-letter-word-game/bin/setup +34 -0
- data/examples/five-letter-word-game/bin/spring +17 -0
- data/examples/five-letter-word-game/bin/update +29 -0
- data/examples/five-letter-word-game/config.ru +5 -0
- data/examples/five-letter-word-game/config/application.rb +12 -0
- data/examples/five-letter-word-game/config/boot.rb +3 -0
- data/examples/five-letter-word-game/config/cable.yml +9 -0
- data/examples/five-letter-word-game/config/database.yml +25 -0
- data/examples/five-letter-word-game/config/environment.rb +5 -0
- data/examples/five-letter-word-game/config/environments/development.rb +56 -0
- data/examples/five-letter-word-game/config/environments/production.rb +86 -0
- data/examples/five-letter-word-game/config/environments/test.rb +42 -0
- data/examples/five-letter-word-game/config/initializers/application_controller_renderer.rb +6 -0
- data/examples/five-letter-word-game/config/initializers/assets.rb +11 -0
- data/examples/five-letter-word-game/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/five-letter-word-game/config/initializers/cookies_serializer.rb +5 -0
- data/examples/five-letter-word-game/config/initializers/filter_parameter_logging.rb +4 -0
- data/examples/five-letter-word-game/config/initializers/hyperloop.rb +3 -0
- data/examples/five-letter-word-game/config/initializers/inflections.rb +16 -0
- data/examples/five-letter-word-game/config/initializers/mime_types.rb +4 -0
- data/examples/five-letter-word-game/config/initializers/new_framework_defaults.rb +24 -0
- data/examples/five-letter-word-game/config/initializers/session_store.rb +3 -0
- data/examples/five-letter-word-game/config/initializers/wrap_parameters.rb +14 -0
- data/examples/five-letter-word-game/config/locales/en.yml +23 -0
- data/examples/five-letter-word-game/config/puma.rb +47 -0
- data/examples/five-letter-word-game/config/routes.rb +5 -0
- data/examples/five-letter-word-game/config/secrets.yml +22 -0
- data/examples/five-letter-word-game/config/spring.rb +6 -0
- data/examples/five-letter-word-game/db/schema.rb +28 -0
- data/examples/five-letter-word-game/db/seeds.rb +7 -0
- data/examples/five-letter-word-game/lib/assets/.keep +0 -0
- data/examples/five-letter-word-game/lib/tasks/.keep +0 -0
- data/examples/five-letter-word-game/log/.keep +0 -0
- data/examples/five-letter-word-game/public/404.html +67 -0
- data/examples/five-letter-word-game/public/422.html +67 -0
- data/examples/five-letter-word-game/public/500.html +66 -0
- data/examples/five-letter-word-game/public/apple-touch-icon-precomposed.png +0 -0
- data/examples/five-letter-word-game/public/apple-touch-icon.png +0 -0
- data/examples/five-letter-word-game/public/favicon.ico +0 -0
- data/examples/five-letter-word-game/public/robots.txt +5 -0
- data/examples/five-letter-word-game/test/controllers/.keep +0 -0
- data/examples/five-letter-word-game/test/fixtures/.keep +0 -0
- data/examples/five-letter-word-game/test/fixtures/files/.keep +0 -0
- data/examples/five-letter-word-game/test/helpers/.keep +0 -0
- data/examples/five-letter-word-game/test/integration/.keep +0 -0
- data/examples/five-letter-word-game/test/mailers/.keep +0 -0
- data/examples/five-letter-word-game/test/models/.keep +0 -0
- data/examples/five-letter-word-game/test/test_helper.rb +10 -0
- data/examples/five-letter-word-game/tmp/.keep +0 -0
- data/examples/five-letter-word-game/vendor/assets/javascripts/.keep +0 -0
- data/examples/five-letter-word-game/vendor/assets/stylesheets/.keep +0 -0
- data/examples/smoke_test/.gitignore +21 -0
- data/examples/smoke_test/Gemfile +59 -0
- data/examples/smoke_test/Gemfile.lock +289 -0
- data/examples/smoke_test/README.md +24 -0
- data/examples/smoke_test/Rakefile +6 -0
- data/examples/smoke_test/app/assets/config/manifest.js +3 -0
- data/examples/smoke_test/app/assets/images/.keep +0 -0
- data/examples/smoke_test/app/assets/javascripts/application.js +15 -0
- data/examples/smoke_test/app/assets/javascripts/cable.js +13 -0
- data/examples/smoke_test/app/assets/javascripts/channels/.keep +0 -0
- data/examples/smoke_test/app/assets/stylesheets/application.css +15 -0
- data/examples/smoke_test/app/channels/application_cable/channel.rb +4 -0
- data/examples/smoke_test/app/channels/application_cable/connection.rb +4 -0
- data/examples/smoke_test/app/controllers/app_controller.rb +5 -0
- data/examples/smoke_test/app/controllers/application_controller.rb +3 -0
- data/examples/smoke_test/app/helpers/application_helper.rb +2 -0
- data/examples/smoke_test/app/hyperloop/components/hello.rb +25 -0
- data/examples/smoke_test/app/hyperloop/operations/operations/nested_send_to_all.rb +7 -0
- data/examples/smoke_test/app/hyperloop/operations/send_to_all.rb +6 -0
- data/examples/smoke_test/app/hyperloop/stores/messages.rb +4 -0
- data/examples/smoke_test/app/jobs/application_job.rb +2 -0
- data/examples/smoke_test/app/mailers/application_mailer.rb +4 -0
- data/examples/smoke_test/app/models/application_record.rb +3 -0
- data/examples/smoke_test/app/models/concerns/.keep +0 -0
- data/examples/smoke_test/app/policies/application_policy.rb +8 -0
- data/examples/smoke_test/app/views/layouts/application.html.erb +14 -0
- data/examples/smoke_test/app/views/layouts/mailer.html.erb +13 -0
- data/examples/smoke_test/app/views/layouts/mailer.text.erb +1 -0
- data/examples/smoke_test/bin/bundle +3 -0
- data/examples/smoke_test/bin/rails +9 -0
- data/examples/smoke_test/bin/rake +9 -0
- data/examples/smoke_test/bin/setup +34 -0
- data/examples/smoke_test/bin/spring +17 -0
- data/examples/smoke_test/bin/update +29 -0
- data/examples/smoke_test/config.ru +5 -0
- data/examples/smoke_test/config/application.rb +15 -0
- data/examples/smoke_test/config/boot.rb +3 -0
- data/examples/smoke_test/config/cable.yml +9 -0
- data/examples/smoke_test/config/database.yml +25 -0
- data/examples/smoke_test/config/environment.rb +5 -0
- data/examples/smoke_test/config/environments/development.rb +54 -0
- data/examples/smoke_test/config/environments/production.rb +86 -0
- data/examples/smoke_test/config/environments/test.rb +42 -0
- data/examples/smoke_test/config/initializers/application_controller_renderer.rb +6 -0
- data/examples/smoke_test/config/initializers/assets.rb +11 -0
- data/examples/smoke_test/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/smoke_test/config/initializers/cookies_serializer.rb +5 -0
- data/examples/smoke_test/config/initializers/filter_parameter_logging.rb +4 -0
- data/examples/smoke_test/config/initializers/hyperloop.rb +32 -0
- data/examples/smoke_test/config/initializers/inflections.rb +16 -0
- data/examples/smoke_test/config/initializers/mime_types.rb +4 -0
- data/examples/smoke_test/config/initializers/new_framework_defaults.rb +24 -0
- data/examples/smoke_test/config/initializers/session_store.rb +3 -0
- data/examples/smoke_test/config/initializers/wrap_parameters.rb +14 -0
- data/examples/smoke_test/config/locales/en.yml +23 -0
- data/examples/smoke_test/config/puma.rb +47 -0
- data/examples/smoke_test/config/routes.rb +5 -0
- data/examples/smoke_test/config/secrets.yml +22 -0
- data/examples/smoke_test/config/spring.rb +6 -0
- data/examples/smoke_test/db/seeds.rb +7 -0
- data/examples/smoke_test/lib/assets/.keep +0 -0
- data/examples/smoke_test/lib/tasks/.keep +0 -0
- data/examples/smoke_test/log/.keep +0 -0
- data/examples/smoke_test/public/404.html +67 -0
- data/examples/smoke_test/public/422.html +67 -0
- data/examples/smoke_test/public/500.html +66 -0
- data/examples/smoke_test/public/apple-touch-icon-precomposed.png +0 -0
- data/examples/smoke_test/public/apple-touch-icon.png +0 -0
- data/examples/smoke_test/public/favicon.ico +0 -0
- data/examples/smoke_test/public/robots.txt +5 -0
- data/examples/smoke_test/test/controllers/.keep +0 -0
- data/examples/smoke_test/test/fixtures/.keep +0 -0
- data/examples/smoke_test/test/fixtures/files/.keep +0 -0
- data/examples/smoke_test/test/helpers/.keep +0 -0
- data/examples/smoke_test/test/integration/.keep +0 -0
- data/examples/smoke_test/test/mailers/.keep +0 -0
- data/examples/smoke_test/test/models/.keep +0 -0
- data/examples/smoke_test/test/test_helper.rb +10 -0
- data/examples/smoke_test/tmp/.keep +0 -0
- data/examples/smoke_test/vendor/assets/javascripts/.keep +0 -0
- data/examples/smoke_test/vendor/assets/stylesheets/.keep +0 -0
- data/hyper-operation.gemspec +44 -0
- data/lib/hyper-operation.rb +59 -0
- data/lib/hyper-operation/api.rb +154 -0
- data/lib/hyper-operation/boot.rb +24 -0
- data/lib/hyper-operation/call_by_class_name.rb +60 -0
- data/lib/hyper-operation/delay_and_interval.rb +9 -0
- data/lib/hyper-operation/engine.rb +11 -0
- data/lib/hyper-operation/exception.rb +13 -0
- data/lib/hyper-operation/filters/acting_user.rb +19 -0
- data/lib/hyper-operation/filters/outbound_filter.rb +9 -0
- data/lib/hyper-operation/filters/simple_hash.rb +22 -0
- data/lib/hyper-operation/opal_patches.rb +39 -0
- data/lib/hyper-operation/promise.rb +347 -0
- data/lib/hyper-operation/railway.rb +5 -0
- data/lib/hyper-operation/railway/dispatcher.rb +31 -0
- data/lib/hyper-operation/railway/operation_wrapper.rb +106 -0
- data/lib/hyper-operation/railway/params_wrapper.rb +124 -0
- data/lib/hyper-operation/railway/run.rb +140 -0
- data/lib/hyper-operation/railway/validations.rb +63 -0
- data/lib/hyper-operation/server_op.rb +98 -0
- data/lib/hyper-operation/transport/acting_user.rb +6 -0
- data/lib/hyper-operation/transport/action_cable.rb +39 -0
- data/lib/hyper-operation/transport/active_record.rb +15 -0
- data/lib/hyper-operation/transport/client_drivers.rb +210 -0
- data/lib/hyper-operation/transport/connection.rb +170 -0
- data/lib/hyper-operation/transport/hyperloop.rb +165 -0
- data/lib/hyper-operation/transport/hyperloop_controller.rb +184 -0
- data/lib/hyper-operation/transport/pluck.rb +6 -0
- data/lib/hyper-operation/transport/policy.rb +535 -0
- data/lib/hyper-operation/version.rb +5 -0
- data/lib/sources/hyperloop/pusher.js +98 -0
- metadata +628 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
# README
|
2
|
+
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
4
|
+
application up and running.
|
5
|
+
|
6
|
+
Things you may want to cover:
|
7
|
+
|
8
|
+
* Ruby version
|
9
|
+
|
10
|
+
* System dependencies
|
11
|
+
|
12
|
+
* Configuration
|
13
|
+
|
14
|
+
* Database creation
|
15
|
+
|
16
|
+
* Database initialization
|
17
|
+
|
18
|
+
* How to run the test suite
|
19
|
+
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
21
|
+
|
22
|
+
* Deployment instructions
|
23
|
+
|
24
|
+
* ...
|
File without changes
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// Action Cable provides the framework to deal with WebSockets in Rails.
|
2
|
+
// You can generate new channels where WebSocket features live using the rails generate channel command.
|
3
|
+
//
|
4
|
+
//= require action_cable
|
5
|
+
//= require_self
|
6
|
+
//= require_tree ./channels
|
7
|
+
|
8
|
+
(function() {
|
9
|
+
this.App || (this.App = {});
|
10
|
+
|
11
|
+
App.cable = ActionCable.createConsumer();
|
12
|
+
|
13
|
+
}).call(this);
|
File without changes
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,14 @@
|
|
1
|
+
::User # force User Model to load so we can get the policies up!
|
2
|
+
# Note is important to fully qualify the name otherwise rails gets
|
3
|
+
# confused when autoloading, and you will get an error when files changed
|
4
|
+
# during development. see http://stackoverflow.com/questions/17561697/argumenterror-a-copy-of-applicationcontroller-has-been-removed-from-the-module/23008837#23008837
|
5
|
+
|
6
|
+
class ApplicationController < ActionController::Base
|
7
|
+
protect_from_forgery with: :exception
|
8
|
+
|
9
|
+
def acting_user
|
10
|
+
session.delete 'hyperloop-dummy-init' unless session.id
|
11
|
+
::User.find(session.id)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
File without changes
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'stores/store'
|
2
|
+
class App < React::Component::Base
|
3
|
+
|
4
|
+
render(DIV) do
|
5
|
+
puts "rendering: game_state = #{Store.game_state}"
|
6
|
+
puts "their_id: #{Store.state.their_id}, my_id: #{Store.my_id} words: #{Store.state.word}"
|
7
|
+
DIV { Store.message } if Store.message
|
8
|
+
send Store.game_state # for each game_state we have a method below...
|
9
|
+
Guesses() unless Store.my_guesses.empty?
|
10
|
+
end
|
11
|
+
|
12
|
+
def initializing
|
13
|
+
SPAN { '...' }
|
14
|
+
end
|
15
|
+
|
16
|
+
def picking_word
|
17
|
+
InputWord label: 'pick a five letter word', button: 'play', operation: Ops::ReadyToPlay
|
18
|
+
end
|
19
|
+
|
20
|
+
def waiting_for_other_player
|
21
|
+
SPAN { "Your word is: #{Store.my_word}. Waiting for the other player to pick their word..." }
|
22
|
+
BUTTON { 'Change Your Word' }.on(:click) { Ops::ChangeWord() }
|
23
|
+
end
|
24
|
+
|
25
|
+
def waiting_for_your_guess
|
26
|
+
InputWord label: 'guess a word', button: 'guess', operation: Ops::Guess
|
27
|
+
end
|
28
|
+
|
29
|
+
def waiting_for_their_guess
|
30
|
+
SPAN { 'waiting for the other player to guess...' }
|
31
|
+
end
|
32
|
+
|
33
|
+
def waiting_for_a_clue_from_them
|
34
|
+
SPAN { 'waiting for the other player to give you the number correct...' }
|
35
|
+
end
|
36
|
+
|
37
|
+
def waiting_for_a_clue_from_you
|
38
|
+
SPAN { "Your word is '#{Store.my_word}'." }
|
39
|
+
SELECT do
|
40
|
+
OPTION(selected: true, disabled: true) { "How many correct in '#{Store.current_guess}'?" }
|
41
|
+
(0..5).each { |count| OPTION(value: count) { count.to_s } }
|
42
|
+
OPTION(value: :win) { "#{Store.current_guess} is correct!"}
|
43
|
+
end.on(:change) do |e|
|
44
|
+
if e.target.value == :win
|
45
|
+
Ops::YouWin()
|
46
|
+
else
|
47
|
+
Ops::Clue their_word: Store.current_guess, my_word: Store.my_word, correct: e.target.value
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def you_win
|
53
|
+
DIV { "YOU WIN :-)" }
|
54
|
+
play_again
|
55
|
+
end
|
56
|
+
|
57
|
+
def they_win
|
58
|
+
DIV { "they won :-("}
|
59
|
+
play_again
|
60
|
+
end
|
61
|
+
|
62
|
+
def play_again
|
63
|
+
BUTTON { 'Play Again!' }.on(:click) { Ops::PlayAgain() }
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class InputWord < React::Component::Base
|
2
|
+
param :label
|
3
|
+
param :button
|
4
|
+
param :operation
|
5
|
+
render(DIV) do
|
6
|
+
LABEL { params.label }
|
7
|
+
INPUT(class: :word)
|
8
|
+
BUTTON { params.button }.on(:click) do
|
9
|
+
params.operation.run(word: Element[dom_node].find('.word').value)
|
10
|
+
.fail { |e| alert e.message }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# dummy user model... just creates an object that responds to #id and
|
2
|
+
# is equal to all other instances that have the the same id
|
3
|
+
class User
|
4
|
+
def initialize(id)
|
5
|
+
@id = id
|
6
|
+
end
|
7
|
+
|
8
|
+
def ==(other)
|
9
|
+
other && id == other.id
|
10
|
+
end
|
11
|
+
|
12
|
+
def eql?(other)
|
13
|
+
self == other
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.find(id)
|
17
|
+
new(id) if id
|
18
|
+
end
|
19
|
+
|
20
|
+
def hash
|
21
|
+
id.hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def id
|
25
|
+
@id.to_s
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Ops
|
2
|
+
class Base < Hyperloop::ServerOp
|
3
|
+
# base class for all the other server side operations
|
4
|
+
# All operations take the acting_user and add outbound
|
5
|
+
# sender and other_player params which are just the ids.
|
6
|
+
|
7
|
+
param :acting_user
|
8
|
+
outbound :sender
|
9
|
+
outbound :other_player
|
10
|
+
|
11
|
+
# partners holds a hash of partner pairs i.e. x => y, y => x
|
12
|
+
# if z is waiting for a partner the hash holds z => nil
|
13
|
+
|
14
|
+
def self.partners
|
15
|
+
@partners ||= {}
|
16
|
+
end
|
17
|
+
|
18
|
+
# find the waiting player
|
19
|
+
|
20
|
+
def waiting_player
|
21
|
+
Base.partners.key(nil)
|
22
|
+
end
|
23
|
+
|
24
|
+
# for a given acting user find the partner
|
25
|
+
|
26
|
+
def other_player
|
27
|
+
Base.partners[params.acting_user]
|
28
|
+
end
|
29
|
+
|
30
|
+
# either attach the acting_user to the waiting player
|
31
|
+
# of if there is no waiting player, make acting_user the waiting player
|
32
|
+
|
33
|
+
def partner_up
|
34
|
+
if waiting_player
|
35
|
+
params.other_player = waiting_player.id
|
36
|
+
Base.partners[params.acting_user] = waiting_player
|
37
|
+
Base.partners[waiting_player] = params.acting_user
|
38
|
+
elsif !Base.partners.key?(params.acting_user)
|
39
|
+
Base.partners[params.acting_user] = nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# unhook partners at game end
|
44
|
+
|
45
|
+
def unpartner
|
46
|
+
Base.partners.delete other_player
|
47
|
+
Base.partners.delete params.acting_user
|
48
|
+
end
|
49
|
+
|
50
|
+
# check words for validity
|
51
|
+
|
52
|
+
def five_unique_letters
|
53
|
+
return true if params.word.split('').uniq.join =~ /^[a-zA-Z]{5}$/
|
54
|
+
abort "words and guesses must have 5 different letters"
|
55
|
+
end
|
56
|
+
|
57
|
+
# check clue for accuracy
|
58
|
+
|
59
|
+
def check_clue
|
60
|
+
params.true_count =
|
61
|
+
(Set.new(params.their_word.split('')) & params.my_word.split('')).count
|
62
|
+
end
|
63
|
+
|
64
|
+
# grab the ids from the two players
|
65
|
+
step { params.other_player = other_player && other_player.id }
|
66
|
+
step { params.sender = params.acting_user.id }
|
67
|
+
# save the value of other player in case the subclass changes it
|
68
|
+
step { @current_other_player = other_player }
|
69
|
+
|
70
|
+
# dispatch to both players. The other player may be set or removed during
|
71
|
+
# the operation, so we dispatch to the before and after values
|
72
|
+
dispatch_to { [params.acting_user, other_player, @current_other_player] }
|
73
|
+
end
|
74
|
+
|
75
|
+
class ReadyToPlay < Base
|
76
|
+
param :word, type: String
|
77
|
+
validate :five_unique_letters
|
78
|
+
end
|
79
|
+
|
80
|
+
class ChangeWord < Base
|
81
|
+
end
|
82
|
+
|
83
|
+
class Guess < Base
|
84
|
+
param :word
|
85
|
+
validate :five_unique_letters
|
86
|
+
end
|
87
|
+
|
88
|
+
class Clue < Base
|
89
|
+
param :their_word
|
90
|
+
param :my_word
|
91
|
+
param :correct, type: Integer, min: 0, max: 5
|
92
|
+
outbound :true_count
|
93
|
+
step :check_clue
|
94
|
+
end
|
95
|
+
|
96
|
+
class YouWin < Base
|
97
|
+
param message: nil
|
98
|
+
step :unpartner
|
99
|
+
end
|
100
|
+
|
101
|
+
class Join < Base
|
102
|
+
step :partner_up
|
103
|
+
end
|
104
|
+
|
105
|
+
class ShareState < Base
|
106
|
+
param :guesses
|
107
|
+
param :word
|
108
|
+
param :current_guesser, nils: true
|
109
|
+
param :current_guess, nils: true
|
110
|
+
param :message
|
111
|
+
end
|
112
|
+
|
113
|
+
class PlayAgain < Hyperloop::Operation
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'operations/ops'
|
2
|
+
class Store < Hyperloop::Store
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def my_guesses
|
6
|
+
state.guesses[my_id]
|
7
|
+
end
|
8
|
+
|
9
|
+
def my_word
|
10
|
+
state.word[my_id]
|
11
|
+
end
|
12
|
+
|
13
|
+
state :current_guess, reader: true
|
14
|
+
|
15
|
+
def message
|
16
|
+
state.message[my_id]
|
17
|
+
end
|
18
|
+
|
19
|
+
def my_id
|
20
|
+
Hyperloop::Application.acting_user_id
|
21
|
+
end
|
22
|
+
|
23
|
+
def game_state
|
24
|
+
if !my_word
|
25
|
+
:picking_word
|
26
|
+
elsif !state.word[state.their_id]
|
27
|
+
:waiting_for_other_player
|
28
|
+
elsif state.winner
|
29
|
+
:"#{state.winner == my_id ? 'you' : 'they'}_win"
|
30
|
+
elsif state.current_guess
|
31
|
+
:"waiting_for_a_clue_from_#{state.current_guesser == my_id ? 'them' : 'you'}"
|
32
|
+
else
|
33
|
+
:"waiting_for_#{state.current_guesser == my_id ? 'your' : 'their'}_guess"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def game_over?
|
38
|
+
game_state =~ /_win$/
|
39
|
+
end
|
40
|
+
|
41
|
+
def setup
|
42
|
+
mutate.guesses Hash.new { |guesses, player| guesses[player] = [] }
|
43
|
+
mutate.winner nil
|
44
|
+
mutate.word Hash.new
|
45
|
+
mutate.current_guesser nil
|
46
|
+
mutate.current_guess nil
|
47
|
+
mutate.their_id nil
|
48
|
+
mutate.message Hash.new
|
49
|
+
Ops::Join.run if Hyperloop.on_client?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
receives Ops::Join do |params|
|
54
|
+
puts "receiving Ops::Join(#{params})"
|
55
|
+
if state.their_id && params.sender != my_id
|
56
|
+
Ops::ShareState(
|
57
|
+
guesses: state.guesses,
|
58
|
+
word: state.word,
|
59
|
+
current_guesser: state.current_guesser,
|
60
|
+
current_guess: state.current_guess,
|
61
|
+
message: state.message
|
62
|
+
)
|
63
|
+
else
|
64
|
+
mutate.their_id params.sender != my_id ? params.sender : params.other_player
|
65
|
+
Ops::ReadyToPlay.run(word: state.word[my_id]) if state.word[my_id]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
receives Ops::ShareState do |params|
|
70
|
+
puts "receiving Ops::ShareState(#{params})"
|
71
|
+
if params.sender != my_id
|
72
|
+
params.guesses.each { |player, guesses| mutate.guesses[player] = guesses }
|
73
|
+
mutate.word params.word
|
74
|
+
mutate.current_guesser params.current_guesser
|
75
|
+
mutate.current_guess params.current_guess
|
76
|
+
mutate.message params.message
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
receives Ops::ReadyToPlay do |params|
|
81
|
+
puts "receiving Ops::ReadyToPlay(#{params})"
|
82
|
+
mutate.current_guesser params.sender unless state.current_guesser
|
83
|
+
mutate.word[params.sender] = params.word
|
84
|
+
end
|
85
|
+
|
86
|
+
receives Ops::ChangeWord do |params|
|
87
|
+
puts "receiving Ops::ChangeWord(#{params})"
|
88
|
+
mutate.word[params.sender] = nil
|
89
|
+
mutate.current_guesser nil if params.sender == state.current_guesser
|
90
|
+
end
|
91
|
+
|
92
|
+
receives Ops::Guess do |params|
|
93
|
+
puts "receiving Ops::Guess(#{params})"
|
94
|
+
mutate.current_guess params.word
|
95
|
+
mutate.message({})
|
96
|
+
end
|
97
|
+
|
98
|
+
receives Ops::Clue do |params|
|
99
|
+
puts "receiving Ops::Clue(#{params})"
|
100
|
+
mutate.guesses[params.other_player] << [state.current_guess, params.true_count]
|
101
|
+
if params.true_count == params.correct
|
102
|
+
mutate.current_guesser params.sender
|
103
|
+
else
|
104
|
+
mutate.message[params.sender] =
|
105
|
+
"That was a bogus clue. There are #{params.true_count} correct in #{current_guess}. They get a free guess!"
|
106
|
+
mutate.message[params.other_player] =
|
107
|
+
"They tried to give you a bogus clue! There are #{params.true_count} correct in #{current_guess}. Have a free turn!"
|
108
|
+
end
|
109
|
+
mutate.current_guess nil
|
110
|
+
end
|
111
|
+
|
112
|
+
receives Ops::YouWin do |params|
|
113
|
+
puts "receiving Ops::YouWin(#{params})"
|
114
|
+
mutate.winner params.other_player
|
115
|
+
mutate.message params.message
|
116
|
+
end
|
117
|
+
|
118
|
+
receives Ops::PlayAgain, :setup
|
119
|
+
receives Hyperloop::Application::Boot, :setup
|
120
|
+
end
|