about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
authorBen Harris <ben@tilde.team>2022-01-15 12:10:26 -0500
committerBen Harris <ben@tilde.team>2022-01-15 12:10:26 -0500
commit2c8c227493509175fcdbcba3e6a85f8b954a169e (patch)
tree56c95cb471004fef1bfa4c99e93fdec1716e3840 /app
init
Diffstat (limited to 'app')
-rw-r--r--app/assets/config/manifest.js4
-rw-r--r--app/assets/images/.keep0
-rw-r--r--app/assets/stylesheets/application.css15
-rw-r--r--app/assets/stylesheets/simple.min.css1
-rw-r--r--app/channels/application_cable/channel.rb6
-rw-r--r--app/channels/application_cable/connection.rb6
-rw-r--r--app/controllers/application_controller.rb4
-rw-r--r--app/controllers/concerns/.keep0
-rw-r--r--app/controllers/machines_controller.rb71
-rw-r--r--app/controllers/players_controller.rb71
-rw-r--r--app/helpers/application_helper.rb4
-rw-r--r--app/helpers/machines_helper.rb4
-rw-r--r--app/helpers/players_helper.rb4
-rw-r--r--app/javascript/application.js3
-rw-r--r--app/javascript/controllers/application.js9
-rw-r--r--app/javascript/controllers/hello_controller.js7
-rw-r--r--app/javascript/controllers/index.js11
-rw-r--r--app/jobs/application_job.rb9
-rw-r--r--app/mailers/application_mailer.rb6
-rw-r--r--app/models/application_record.rb5
-rw-r--r--app/models/concerns/.keep0
-rw-r--r--app/models/machine.rb4
-rw-r--r--app/models/player.rb4
-rw-r--r--app/views/layouts/application.html.erb16
-rw-r--r--app/views/layouts/mailer.html.erb14
-rw-r--r--app/views/layouts/mailer.text.erb1
-rw-r--r--app/views/machines/_form.html.erb27
-rw-r--r--app/views/machines/_machine.html.erb12
-rw-r--r--app/views/machines/_machine.json.jbuilder4
-rw-r--r--app/views/machines/edit.html.erb10
-rw-r--r--app/views/machines/index.html.erb14
-rw-r--r--app/views/machines/index.json.jbuilder3
-rw-r--r--app/views/machines/new.html.erb9
-rw-r--r--app/views/machines/show.html.erb10
-rw-r--r--app/views/machines/show.json.jbuilder3
-rw-r--r--app/views/players/_form.html.erb32
-rw-r--r--app/views/players/_player.html.erb17
-rw-r--r--app/views/players/_player.json.jbuilder4
-rw-r--r--app/views/players/edit.html.erb10
-rw-r--r--app/views/players/index.html.erb14
-rw-r--r--app/views/players/index.json.jbuilder3
-rw-r--r--app/views/players/new.html.erb9
-rw-r--r--app/views/players/show.html.erb10
-rw-r--r--app/views/players/show.json.jbuilder3
44 files changed, 473 insertions, 0 deletions
diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js
new file mode 100644
index 0000000..ddd546a
--- /dev/null
+++ b/app/assets/config/manifest.js
@@ -0,0 +1,4 @@
+//= link_tree ../images
+//= link_directory ../stylesheets .css
+//= link_tree ../../javascript .js
+//= link_tree ../../../vendor/javascript .js
diff --git a/app/assets/images/.keep b/app/assets/images/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/assets/images/.keep
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
new file mode 100644
index 0000000..288b9ab
--- /dev/null
+++ b/app/assets/stylesheets/application.css
@@ -0,0 +1,15 @@
+/*
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's
+ * vendor/assets/stylesheets directory can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS
+ * files in this directory. Styles in this file should be added after the last require_* statement.
+ * It is generally better to create a new file per style scope.
+ *
+ *= require_tree .
+ *= require_self
+ */
diff --git a/app/assets/stylesheets/simple.min.css b/app/assets/stylesheets/simple.min.css
new file mode 100644
index 0000000..780399e
--- /dev/null
+++ b/app/assets/stylesheets/simple.min.css
@@ -0,0 +1 @@
+:root{--sans-font:-apple-system,BlinkMacSystemFont,"Avenir Next",Avenir,"Nimbus Sans L",Roboto,Noto,"Segoe UI",Arial,Helvetica,"Helvetica Neue",sans-serif;--mono-font:Consolas,Menlo,Monaco,"Andale Mono","Ubuntu Mono",monospace;--base-fontsize:1.15rem;--header-scale:1.25;--line-height:1.618;--bg:#fff;--accent-bg:#f5f7ff;--text:#212121;--text-light:#585858;--border:#d8dae1;--accent:#0d47a1;--accent-light:#90caf9;--code:#d81b60;--preformatted:#444;--marked:#ffdd33;--disabled:#efefef}@media (prefers-color-scheme:dark){:root{--bg:#212121;--accent-bg:#2b2b2b;--text:#dcdcdc;--text-light:#ababab;--border:#666;--accent:#ffb300;--accent-light:#ffecb3;--code:#f06292;--preformatted:#ccc;--disabled:#111}img,video{opacity:.6}}html{font-family:var(--sans-font)}body{color:var(--text);background:var(--bg);font-size:var(--base-fontsize);line-height:var(--line-height);display:flex;min-height:100vh;flex-direction:column;flex:1;margin:0 auto;max-width:45rem;padding:0 .5rem;overflow-x:hidden;word-break:break-word;overflow-wrap:break-word}header{background:var(--accent-bg);border-bottom:1px solid var(--border);text-align:center;padding:2rem .5rem;width:100vw;position:relative;box-sizing:border-box;left:50%;right:50%;margin-left:-50vw;margin-right:-50vw}header h1,header p{margin:0}main{padding-top:1.5rem}h1,h2,h3{line-height:1.1}nav{font-size:1rem;line-height:2;padding:1rem 0}nav a{margin:1rem 1rem 0 0;border:1px solid var(--border);border-radius:5px;color:var(--text)!important;display:inline-block;padding:.1rem 1rem;text-decoration:none;transition:.4s}nav a:hover{color:var(--accent)!important;border-color:var(--accent)}nav a.current:hover{text-decoration:none}footer{margin-top:4rem;padding:2rem 1rem 1.5rem 1rem;color:var(--text-light);font-size:.9rem;text-align:center;border-top:1px solid var(--border)}h1{font-size:calc(var(--base-fontsize) * var(--header-scale) * var(--header-scale) * var(--header-scale) * var(--header-scale));margin-top:calc(var(--line-height) * 1.5rem)}h2{font-size:calc(var(--base-fontsize) * var(--header-scale) * var(--header-scale) * var(--header-scale));margin-top:calc(var(--line-height) * 1.5rem)}h3{font-size:calc(var(--base-fontsize) * var(--header-scale) * var(--header-scale));margin-top:calc(var(--line-height) * 1.5rem)}h4{font-size:calc(var(--base-fontsize) * var(--header-scale));margin-top:calc(var(--line-height) * 1.5rem)}h5{font-size:var(--base-fontsize);margin-top:calc(var(--line-height) * 1.5rem)}h6{font-size:calc(var(--base-fontsize)/ var(--header-scale));margin-top:calc(var(--line-height) * 1.5rem)}a,a:visited{color:var(--accent)}a:hover{text-decoration:none}[role=button],a button,button,input[type=button],input[type=reset],input[type=submit]{border:none;border-radius:5px;background:var(--accent);font-size:1rem;color:var(--bg);padding:.7rem .9rem;margin:.5rem 0;transition:.4s}[role=button][aria-disabled=true],a button[disabled],button[disabled],input[type=button][disabled],input[type=checkbox][disabled],input[type=radio][disabled],input[type=reset][disabled],input[type=submit][disabled],select[disabled]{cursor:default;opacity:.5;cursor:not-allowed}input:disabled,select:disabled,textarea:disabled{cursor:not-allowed;background-color:var(--disabled)}input[type=range]{padding:0}abbr{cursor:help}[role=button]:focus,[role=button]:not([aria-disabled=true]):hover,button:enabled:hover,button:focus,input[type=button]:enabled:hover,input[type=button]:focus,input[type=checkbox]:enabled:hover,input[type=checkbox]:focus,input[type=radio]:enabled:hover,input[type=radio]:focus,input[type=reset]:enabled:hover,input[type=reset]:focus,input[type=submit]:enabled:hover,input[type=submit]:focus{opacity:.8;cursor:pointer}details{background:var(--accent-bg);border:1px solid var(--border);border-radius:5px;margin-bottom:1rem}summary{cursor:pointer;font-weight:700;padding:.6rem 1rem}details[open]{padding:.6rem 1rem .75rem 1rem}details[open] summary{margin-bottom:.5rem;padding:0}details[open]>:last-child{margin-bottom:0}table{border-collapse:collapse;width:100%;margin:1.5rem 0}td,th{border:1px solid var(--border);text-align:left;padding:.5rem}th{background:var(--accent-bg);font-weight:700}tr:nth-child(even){background:var(--accent-bg)}table caption{font-weight:700;margin-bottom:.5rem}ol,ul{padding-left:3rem}input,select,textarea{font-size:inherit;font-family:inherit;padding:.5rem;margin-bottom:.5rem;color:var(--text);background:var(--bg);border:1px solid var(--border);border-radius:5px;box-shadow:none;box-sizing:border-box;width:60%;-moz-appearance:none;-webkit-appearance:none;appearance:none}select{background-image:linear-gradient(45deg,transparent 49%,var(--text) 51%),linear-gradient(135deg,var(--text) 51%,transparent 49%);background-position:calc(100% - 20px),calc(100% - 15px);background-size:5px 5px,5px 5px;background-repeat:no-repeat}select[multiple]{background-image:none!important}input[type=checkbox],input[type=radio]{vertical-align:bottom;position:relative}input[type=radio]{border-radius:100%}input[type=checkbox]:checked,input[type=radio]:checked{background:var(--accent)}input[type=checkbox]:checked::after{content:" ";width:.1em;height:.25em;border-radius:0;position:absolute;top:.05em;left:.18em;background:0 0;border-right:solid var(--bg) .08em;border-bottom:solid var(--bg) .08em;font-size:1.8em;transform:rotate(45deg)}input[type=radio]:checked::after{content:" ";width:.25em;height:.25em;border-radius:100%;position:absolute;top:.125em;background:var(--bg);left:.125em;font-size:32px}textarea{width:80%}@media only screen and (max-width:720px){input,select,textarea{width:100%}}input[type=checkbox],input[type=radio]{width:auto}input[type=file]{border:0}fieldset{border:0;padding:0;margin:0}hr{color:var(--border);border-top:1px;margin:1rem auto}mark{padding:2px 5px;border-radius:4px;background:var(--marked)}main img,main video{max-width:100%;height:auto;border-radius:5px}figure{margin:0}figcaption{font-size:.9rem;color:var(--text-light);text-align:center;margin-bottom:1rem}blockquote{margin:2rem 0 2rem 2rem;padding:.4rem .8rem;border-left:.35rem solid var(--accent);opacity:.8;font-style:italic}cite{font-size:.9rem;color:var(--text-light);font-style:normal}code,kbd,pre,pre span,samp{font-size:1.075rem;font-family:var(--mono-font);color:var(--code)}kbd{color:var(--preformatted);border:1px solid var(--preformatted);border-bottom:3px solid var(--preformatted);border-radius:5px;padding:.1rem}pre{padding:1rem 1.4rem;max-width:100%;overflow:auto;overflow-x:auto;color:var(--preformatted);background:var(--accent-bg);border:1px solid var(--border);border-radius:5px}pre code{color:var(--preformatted);background:0 0;margin:0;padding:0}
\ No newline at end of file
diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb
new file mode 100644
index 0000000..9aec230
--- /dev/null
+++ b/app/channels/application_cable/channel.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+module ApplicationCable
+  class Channel < ActionCable::Channel::Base
+  end
+end
diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb
new file mode 100644
index 0000000..8d6c2a1
--- /dev/null
+++ b/app/channels/application_cable/connection.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+module ApplicationCable
+  class Connection < ActionCable::Connection::Base
+  end
+end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
new file mode 100644
index 0000000..7944f9f
--- /dev/null
+++ b/app/controllers/application_controller.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+class ApplicationController < ActionController::Base
+end
diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/controllers/concerns/.keep
diff --git a/app/controllers/machines_controller.rb b/app/controllers/machines_controller.rb
new file mode 100644
index 0000000..d83a52f
--- /dev/null
+++ b/app/controllers/machines_controller.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+class MachinesController < ApplicationController
+  before_action :set_machine, only: %i[show edit update destroy]
+
+  # GET /machines or /machines.json
+  def index
+    @machines = Machine.all
+  end
+
+  # GET /machines/1 or /machines/1.json
+  def show; end
+
+  # GET /machines/new
+  def new
+    @machine = Machine.new
+  end
+
+  # GET /machines/1/edit
+  def edit; end
+
+  # POST /machines or /machines.json
+  def create
+    @machine = Machine.new(machine_params)
+
+    respond_to do |format|
+      if @machine.save
+        format.html { redirect_to machine_url(@machine), notice: 'Machine was successfully created.' }
+        format.json { render :show, status: :created, location: @machine }
+      else
+        format.html { render :new, status: :unprocessable_entity }
+        format.json { render json: @machine.errors, status: :unprocessable_entity }
+      end
+    end
+  end
+
+  # PATCH/PUT /machines/1 or /machines/1.json
+  def update
+    respond_to do |format|
+      if @machine.update(machine_params)
+        format.html { redirect_to machine_url(@machine), notice: 'Machine was successfully updated.' }
+        format.json { render :show, status: :ok, location: @machine }
+      else
+        format.html { render :edit, status: :unprocessable_entity }
+        format.json { render json: @machine.errors, status: :unprocessable_entity }
+      end
+    end
+  end
+
+  # DELETE /machines/1 or /machines/1.json
+  def destroy
+    @machine.destroy
+
+    respond_to do |format|
+      format.html { redirect_to machines_url, notice: 'Machine was successfully destroyed.' }
+      format.json { head :no_content }
+    end
+  end
+
+  private
+
+  # Use callbacks to share common setup or constraints between actions.
+  def set_machine
+    @machine = Machine.find(params[:id])
+  end
+
+  # Only allow a list of trusted parameters through.
+  def machine_params
+    params.require(:machine).permit(:name, :edition)
+  end
+end
diff --git a/app/controllers/players_controller.rb b/app/controllers/players_controller.rb
new file mode 100644
index 0000000..c1139e1
--- /dev/null
+++ b/app/controllers/players_controller.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+class PlayersController < ApplicationController
+  before_action :set_player, only: %i[show edit update destroy]
+
+  # GET /players or /players.json
+  def index
+    @players = Player.all
+  end
+
+  # GET /players/1 or /players/1.json
+  def show; end
+
+  # GET /players/new
+  def new
+    @player = Player.new
+  end
+
+  # GET /players/1/edit
+  def edit; end
+
+  # POST /players or /players.json
+  def create
+    @player = Player.new(player_params)
+
+    respond_to do |format|
+      if @player.save
+        format.html { redirect_to player_url(@player), notice: 'Player was successfully created.' }
+        format.json { render :show, status: :created, location: @player }
+      else
+        format.html { render :new, status: :unprocessable_entity }
+        format.json { render json: @player.errors, status: :unprocessable_entity }
+      end
+    end
+  end
+
+  # PATCH/PUT /players/1 or /players/1.json
+  def update
+    respond_to do |format|
+      if @player.update(player_params)
+        format.html { redirect_to player_url(@player), notice: 'Player was successfully updated.' }
+        format.json { render :show, status: :ok, location: @player }
+      else
+        format.html { render :edit, status: :unprocessable_entity }
+        format.json { render json: @player.errors, status: :unprocessable_entity }
+      end
+    end
+  end
+
+  # DELETE /players/1 or /players/1.json
+  def destroy
+    @player.destroy
+
+    respond_to do |format|
+      format.html { redirect_to players_url, notice: 'Player was successfully destroyed.' }
+      format.json { head :no_content }
+    end
+  end
+
+  private
+
+  # Use callbacks to share common setup or constraints between actions.
+  def set_player
+    @player = Player.find(params[:id])
+  end
+
+  # Only allow a list of trusted parameters through.
+  def player_params
+    params.require(:player).permit(:name, :paid, :strikes)
+  end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
new file mode 100644
index 0000000..15b06f0
--- /dev/null
+++ b/app/helpers/application_helper.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+module ApplicationHelper
+end
diff --git a/app/helpers/machines_helper.rb b/app/helpers/machines_helper.rb
new file mode 100644
index 0000000..8750a53
--- /dev/null
+++ b/app/helpers/machines_helper.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+module MachinesHelper
+end
diff --git a/app/helpers/players_helper.rb b/app/helpers/players_helper.rb
new file mode 100644
index 0000000..b7c4045
--- /dev/null
+++ b/app/helpers/players_helper.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+module PlayersHelper
+end
diff --git a/app/javascript/application.js b/app/javascript/application.js
new file mode 100644
index 0000000..0d7b494
--- /dev/null
+++ b/app/javascript/application.js
@@ -0,0 +1,3 @@
+// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
+import "@hotwired/turbo-rails"
+import "controllers"
diff --git a/app/javascript/controllers/application.js b/app/javascript/controllers/application.js
new file mode 100644
index 0000000..1213e85
--- /dev/null
+++ b/app/javascript/controllers/application.js
@@ -0,0 +1,9 @@
+import { Application } from "@hotwired/stimulus"
+
+const application = Application.start()
+
+// Configure Stimulus development experience
+application.debug = false
+window.Stimulus   = application
+
+export { application }
diff --git a/app/javascript/controllers/hello_controller.js b/app/javascript/controllers/hello_controller.js
new file mode 100644
index 0000000..5975c07
--- /dev/null
+++ b/app/javascript/controllers/hello_controller.js
@@ -0,0 +1,7 @@
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+  connect() {
+    this.element.textContent = "Hello World!"
+  }
+}
diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js
new file mode 100644
index 0000000..54ad4ca
--- /dev/null
+++ b/app/javascript/controllers/index.js
@@ -0,0 +1,11 @@
+// Import and register all your controllers from the importmap under controllers/*
+
+import { application } from "controllers/application"
+
+// Eager load all controllers defined in the import map under controllers/**/*_controller
+import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
+eagerLoadControllersFrom("controllers", application)
+
+// Lazy load controllers as they appear in the DOM (remember not to preload controllers in import map!)
+// import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading"
+// lazyLoadControllersFrom("controllers", application)
diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb
new file mode 100644
index 0000000..bef3959
--- /dev/null
+++ b/app/jobs/application_job.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class ApplicationJob < ActiveJob::Base
+  # Automatically retry jobs that encountered a deadlock
+  # retry_on ActiveRecord::Deadlocked
+
+  # Most jobs are safe to ignore if the underlying records are no longer available
+  # discard_on ActiveJob::DeserializationError
+end
diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb
new file mode 100644
index 0000000..d84cb6e
--- /dev/null
+++ b/app/mailers/application_mailer.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+class ApplicationMailer < ActionMailer::Base
+  default from: 'from@example.com'
+  layout 'mailer'
+end
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
new file mode 100644
index 0000000..08dc537
--- /dev/null
+++ b/app/models/application_record.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class ApplicationRecord < ActiveRecord::Base
+  primary_abstract_class
+end
diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/models/concerns/.keep
diff --git a/app/models/machine.rb b/app/models/machine.rb
new file mode 100644
index 0000000..ac9cbd1
--- /dev/null
+++ b/app/models/machine.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+class Machine < ApplicationRecord
+end
diff --git a/app/models/player.rb b/app/models/player.rb
new file mode 100644
index 0000000..f8ebc6d
--- /dev/null
+++ b/app/models/player.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+class Player < ApplicationRecord
+end
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
new file mode 100644
index 0000000..665f897
--- /dev/null
+++ b/app/views/layouts/application.html.erb
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Knockout</title>
+    <meta name="viewport" content="width=device-width,initial-scale=1">
+    <%= csrf_meta_tags %>
+    <%= csp_meta_tag %>
+
+    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
+    <%= javascript_importmap_tags %>
+  </head>
+
+  <body>
+    <%= yield %>
+  </body>
+</html>
diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb
new file mode 100644
index 0000000..4ee4c89
--- /dev/null
+++ b/app/views/layouts/mailer.html.erb
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <style>
+      /* Email styles need to be inline */
+    </style>
+    <title></title>
+  </head>
+
+  <body>
+    <%= yield %>
+  </body>
+</html>
diff --git a/app/views/layouts/mailer.text.erb b/app/views/layouts/mailer.text.erb
new file mode 100644
index 0000000..37f0bdd
--- /dev/null
+++ b/app/views/layouts/mailer.text.erb
@@ -0,0 +1 @@
+<%= yield %>
diff --git a/app/views/machines/_form.html.erb b/app/views/machines/_form.html.erb
new file mode 100644
index 0000000..0e59129
--- /dev/null
+++ b/app/views/machines/_form.html.erb
@@ -0,0 +1,27 @@
+<%= form_with(model: machine) do |form| %>
+  <% if machine.errors.any? %>
+    <div style="color: red">
+      <h2><%= pluralize(machine.errors.count, "error") %> prohibited this machine from being saved:</h2>
+
+      <ul>
+        <% machine.errors.each do |error| %>
+          <li><%= error.full_message %></li>
+        <% end %>
+      </ul>
+    </div>
+  <% end %>
+
+  <div>
+    <%= form.label :name, style: "display: block" %>
+    <%= form.text_field :name %>
+  </div>
+
+  <div>
+    <%= form.label :edition, style: "display: block" %>
+    <%= form.text_field :edition %>
+  </div>
+
+  <div>
+    <%= form.submit %>
+  </div>
+<% end %>
diff --git a/app/views/machines/_machine.html.erb b/app/views/machines/_machine.html.erb
new file mode 100644
index 0000000..edba53e
--- /dev/null
+++ b/app/views/machines/_machine.html.erb
@@ -0,0 +1,12 @@
+<div id="<%= dom_id machine %>">
+  <p>
+    <strong>Name:</strong>
+    <%= machine.name %>
+  </p>
+
+  <p>
+    <strong>Edition:</strong>
+    <%= machine.edition %>
+  </p>
+
+</div>
diff --git a/app/views/machines/_machine.json.jbuilder b/app/views/machines/_machine.json.jbuilder
new file mode 100644
index 0000000..ef51e42
--- /dev/null
+++ b/app/views/machines/_machine.json.jbuilder
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+json.extract! machine, :id, :name, :edition, :created_at, :updated_at
+json.url machine_url(machine, format: :json)
diff --git a/app/views/machines/edit.html.erb b/app/views/machines/edit.html.erb
new file mode 100644
index 0000000..a390477
--- /dev/null
+++ b/app/views/machines/edit.html.erb
@@ -0,0 +1,10 @@
+<h1>Editing machine</h1>
+
+<%= render "form", machine: @machine %>
+
+<br>
+
+<div>
+  <%= link_to "Show this machine", @machine %> |
+  <%= link_to "Back to machines", machines_path %>
+</div>
diff --git a/app/views/machines/index.html.erb b/app/views/machines/index.html.erb
new file mode 100644
index 0000000..b5e2c85
--- /dev/null
+++ b/app/views/machines/index.html.erb
@@ -0,0 +1,14 @@
+<p style="color: green"><%= notice %></p>
+
+<h1>Machines</h1>
+
+<div id="machines">
+  <% @machines.each do |machine| %>
+    <%= render machine %>
+    <p>
+      <%= link_to "Show this machine", machine %>
+    </p>
+  <% end %>
+</div>
+
+<%= link_to "New machine", new_machine_path %>
diff --git a/app/views/machines/index.json.jbuilder b/app/views/machines/index.json.jbuilder
new file mode 100644
index 0000000..9947db2
--- /dev/null
+++ b/app/views/machines/index.json.jbuilder
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+json.array! @machines, partial: 'machines/machine', as: :machine
diff --git a/app/views/machines/new.html.erb b/app/views/machines/new.html.erb
new file mode 100644
index 0000000..ae58280
--- /dev/null
+++ b/app/views/machines/new.html.erb
@@ -0,0 +1,9 @@
+<h1>New machine</h1>
+
+<%= render "form", machine: @machine %>
+
+<br>
+
+<div>
+  <%= link_to "Back to machines", machines_path %>
+</div>
diff --git a/app/views/machines/show.html.erb b/app/views/machines/show.html.erb
new file mode 100644
index 0000000..1af79f9
--- /dev/null
+++ b/app/views/machines/show.html.erb
@@ -0,0 +1,10 @@
+<p style="color: green"><%= notice %></p>
+
+<%= render @machine %>
+
+<div>
+  <%= link_to "Edit this machine", edit_machine_path(@machine) %> |
+  <%= link_to "Back to machines", machines_path %>
+
+  <%= button_to "Destroy this machine", @machine, method: :delete %>
+</div>
diff --git a/app/views/machines/show.json.jbuilder b/app/views/machines/show.json.jbuilder
new file mode 100644
index 0000000..21b2852
--- /dev/null
+++ b/app/views/machines/show.json.jbuilder
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+json.partial! 'machines/machine', machine: @machine
diff --git a/app/views/players/_form.html.erb b/app/views/players/_form.html.erb
new file mode 100644
index 0000000..48dadc5
--- /dev/null
+++ b/app/views/players/_form.html.erb
@@ -0,0 +1,32 @@
+<%= form_with(model: player) do |form| %>
+  <% if player.errors.any? %>
+    <div style="color: red">
+      <h2><%= pluralize(player.errors.count, "error") %> prohibited this player from being saved:</h2>
+
+      <ul>
+        <% player.errors.each do |error| %>
+          <li><%= error.full_message %></li>
+        <% end %>
+      </ul>
+    </div>
+  <% end %>
+
+  <div>
+    <%= form.label :name, style: "display: block" %>
+    <%= form.text_field :name %>
+  </div>
+
+  <div>
+    <%= form.label :paid, style: "display: block" %>
+    <%= form.check_box :paid %>
+  </div>
+
+  <div>
+    <%= form.label :strikes, style: "display: block" %>
+    <%= form.number_field :strikes %>
+  </div>
+
+  <div>
+    <%= form.submit %>
+  </div>
+<% end %>
diff --git a/app/views/players/_player.html.erb b/app/views/players/_player.html.erb
new file mode 100644
index 0000000..35e7cb1
--- /dev/null
+++ b/app/views/players/_player.html.erb
@@ -0,0 +1,17 @@
+<div id="<%= dom_id player %>">
+  <p>
+    <strong>Name:</strong>
+    <%= player.name %>
+  </p>
+
+  <p>
+    <strong>Paid:</strong>
+    <%= player.paid %>
+  </p>
+
+  <p>
+    <strong>Strikes:</strong>
+    <%= player.strikes %>
+  </p>
+
+</div>
diff --git a/app/views/players/_player.json.jbuilder b/app/views/players/_player.json.jbuilder
new file mode 100644
index 0000000..deda657
--- /dev/null
+++ b/app/views/players/_player.json.jbuilder
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+json.extract! player, :id, :name, :paid, :strikes, :created_at, :updated_at
+json.url player_url(player, format: :json)
diff --git a/app/views/players/edit.html.erb b/app/views/players/edit.html.erb
new file mode 100644
index 0000000..a6cea2b
--- /dev/null
+++ b/app/views/players/edit.html.erb
@@ -0,0 +1,10 @@
+<h1>Editing player</h1>
+
+<%= render "form", player: @player %>
+
+<br>
+
+<div>
+  <%= link_to "Show this player", @player %> |
+  <%= link_to "Back to players", players_path %>
+</div>
diff --git a/app/views/players/index.html.erb b/app/views/players/index.html.erb
new file mode 100644
index 0000000..eac7710
--- /dev/null
+++ b/app/views/players/index.html.erb
@@ -0,0 +1,14 @@
+<p style="color: green"><%= notice %></p>
+
+<h1>Players</h1>
+
+<div id="players">
+  <% @players.each do |player| %>
+    <%= render player %>
+    <p>
+      <%= link_to "Show this player", player %>
+    </p>
+  <% end %>
+</div>
+
+<%= link_to "New player", new_player_path %>
diff --git a/app/views/players/index.json.jbuilder b/app/views/players/index.json.jbuilder
new file mode 100644
index 0000000..da56f8d
--- /dev/null
+++ b/app/views/players/index.json.jbuilder
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+json.array! @players, partial: 'players/player', as: :player
diff --git a/app/views/players/new.html.erb b/app/views/players/new.html.erb
new file mode 100644
index 0000000..c248abe
--- /dev/null
+++ b/app/views/players/new.html.erb
@@ -0,0 +1,9 @@
+<h1>New player</h1>
+
+<%= render "form", player: @player %>
+
+<br>
+
+<div>
+  <%= link_to "Back to players", players_path %>
+</div>
diff --git a/app/views/players/show.html.erb b/app/views/players/show.html.erb
new file mode 100644
index 0000000..19ade1d
--- /dev/null
+++ b/app/views/players/show.html.erb
@@ -0,0 +1,10 @@
+<p style="color: green"><%= notice %></p>
+
+<%= render @player %>
+
+<div>
+  <%= link_to "Edit this player", edit_player_path(@player) %> |
+  <%= link_to "Back to players", players_path %>
+
+  <%= button_to "Destroy this player", @player, method: :delete %>
+</div>
diff --git a/app/views/players/show.json.jbuilder b/app/views/players/show.json.jbuilder
new file mode 100644
index 0000000..07dba4a
--- /dev/null
+++ b/app/views/players/show.json.jbuilder
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+json.partial! 'players/player', player: @player