main
parent
b19a8260c7
commit
3384461caa
@ -1,196 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
require_relative "models"
|
|
||||||
require_relative "views"
|
|
||||||
|
|
||||||
require "roda"
|
|
||||||
|
|
||||||
module RankKing
|
|
||||||
module Models
|
|
||||||
require "sequel/model"
|
|
||||||
require_relative "db"
|
|
||||||
|
|
||||||
class Pool < Sequel::Model
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class App < Roda
|
|
||||||
opts[:check_dynamic_arity] = false
|
|
||||||
opts[:check_arity] = :warn
|
|
||||||
|
|
||||||
plugin :default_headers,
|
|
||||||
"Content-Type" => "text/html",
|
|
||||||
# "Strict-Transport-Security" => "max-age=16070400;", # Uncomment if only allowing https:// access
|
|
||||||
"X-Frame-Options" => "deny",
|
|
||||||
"X-Content-Type-Options" => "nosniff",
|
|
||||||
"X-XSS-Protection" => "1; mode=block"
|
|
||||||
|
|
||||||
plugin :content_security_policy do |csp|
|
|
||||||
csp.default_src :none
|
|
||||||
# csp.style_src :self, "https://cdn.jsdelivr.net"
|
|
||||||
csp.form_action :self
|
|
||||||
csp.script_src :self
|
|
||||||
csp.connect_src :self
|
|
||||||
csp.base_uri :none
|
|
||||||
csp.frame_ancestors :none
|
|
||||||
end
|
|
||||||
|
|
||||||
css_opts = {cache: false, style: :compressed}
|
|
||||||
# :nocov:
|
|
||||||
if ENV["RACK_ENV"] == 'development'
|
|
||||||
css_opts.merge!(source_map_embed: true, source_map_contents: true, source_map_file: ".")
|
|
||||||
end
|
|
||||||
plugin :render_coverage if defined?(SimpleCov)
|
|
||||||
# :nocov:
|
|
||||||
|
|
||||||
plugin :route_csrf
|
|
||||||
plugin :flash
|
|
||||||
# plugin :assets, css: "app.scss", css_opts: css_opts, timestamp_paths: true
|
|
||||||
# plugin :render, escape: true, layout: "./layout", :template_opts=>{chain_appends: !defined?(SimpleCov), freeze: true, skip_compiled_encoding_detection: true}
|
|
||||||
plugin :public
|
|
||||||
plugin :Integer_matcher_max
|
|
||||||
plugin :typecast_params_sized_integers, sizes: [64], default_size: 64
|
|
||||||
# plugin :hash_branch_view_subdir
|
|
||||||
plugin :custom_block_results
|
|
||||||
|
|
||||||
logger = if ENV["RACK_ENV"] == "test"
|
|
||||||
Class.new{def write(_) end}.new
|
|
||||||
else
|
|
||||||
$stderr
|
|
||||||
end
|
|
||||||
plugin :common_logger, logger
|
|
||||||
|
|
||||||
plugin :not_found do
|
|
||||||
Views::Layout.call(title: "File Not Found")
|
|
||||||
end
|
|
||||||
|
|
||||||
if ENV["RACK_ENV"] == "development"
|
|
||||||
plugin :exception_page
|
|
||||||
class RodaRequest
|
|
||||||
def assets
|
|
||||||
exception_page_assets
|
|
||||||
super
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
def self.freeze
|
|
||||||
Sequel::Model.freeze_descendents
|
|
||||||
DB.freeze
|
|
||||||
super
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
plugin :error_handler do |e|
|
|
||||||
case e
|
|
||||||
when Roda::RodaPlugins::RouteCsrf::InvalidToken
|
|
||||||
@page_title = "Invalid Security Token"
|
|
||||||
response.status = 400
|
|
||||||
view(content: "<p>An invalid security token was submitted with this request, and this request could not be processed.</p>")
|
|
||||||
else
|
|
||||||
$stderr.print "#{e.class}: #{e.message}\n"
|
|
||||||
$stderr.puts e.backtrace
|
|
||||||
next exception_page(e, assets: true) if ENV["RACK_ENV"] == "development"
|
|
||||||
# @page_title = "Internal Server Error"
|
|
||||||
# view(content: "")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
plugin :sessions,
|
|
||||||
key: "_App.session",
|
|
||||||
#cookie_options: {secure: ENV['RACK_ENV'] != 'test'}, # Uncomment if only allowing https:// access
|
|
||||||
secret: ENV.send((ENV["RACK_ENV"] == "development" ? :[] : :delete), "APP_SESSION_SECRET")
|
|
||||||
|
|
||||||
# if Unreloader.autoload?
|
|
||||||
# plugin :autoload_hash_branches
|
|
||||||
# autoload_hash_branch_dir("./routes")
|
|
||||||
# end
|
|
||||||
# Unreloader.autoload("routes", delete_hook: proc{|f| hash_branch(File.basename(f).delete_suffix(".rb"))}){}
|
|
||||||
|
|
||||||
class Template < Phlex::HTML
|
|
||||||
def initialize(block)
|
|
||||||
@block = block
|
|
||||||
end
|
|
||||||
|
|
||||||
def template
|
|
||||||
instance_eval(&@block)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# def render(&block)
|
|
||||||
# template = Template.new(block)
|
|
||||||
# instance_variables
|
|
||||||
# .reject { _1.start_with?("@_") }
|
|
||||||
# .each { template.instance_variable_set(_1, instance_variable_get(_1)) }
|
|
||||||
# Views::Layout.call do
|
|
||||||
# plain ""
|
|
||||||
# end
|
|
||||||
# # Views::Layout.call(template)
|
|
||||||
# # Views::Layout.call do |layout|
|
|
||||||
# # layout.page_title "New Pool"
|
|
||||||
# # plain ""
|
|
||||||
# # end
|
|
||||||
# end
|
|
||||||
|
|
||||||
def view(&block)
|
|
||||||
Class.new(Phlex::HTML, &block).call
|
|
||||||
end
|
|
||||||
|
|
||||||
route do |r|
|
|
||||||
|
|
||||||
# r.public
|
|
||||||
# r.assets
|
|
||||||
check_csrf!
|
|
||||||
|
|
||||||
r.root do
|
|
||||||
if DB[:pools].empty?
|
|
||||||
r.redirect "/pools/new"
|
|
||||||
else
|
|
||||||
render do
|
|
||||||
h1 { "ohai" }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
r.on "pools" do
|
|
||||||
r.is "new" do
|
|
||||||
r.get do
|
|
||||||
@csrf_token = csrf_token(r.path)
|
|
||||||
view do
|
|
||||||
Views::Layout.new(title: "New Pool") do
|
|
||||||
Views::NewPool.new(csrf_token: @csrf_token)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
# Views::Layout.call(title: "New Pool") do
|
|
||||||
# render Views::NewPool.new(csrf_token: csrf_token(r.path))
|
|
||||||
# end
|
|
||||||
# layout = Views::Layout.new do |layout|
|
|
||||||
# layout.page_title "New Pool"
|
|
||||||
# render Views::NewPool.new(csrf_token: csrf_token(r.path))
|
|
||||||
# end
|
|
||||||
# layout.call
|
|
||||||
# @csrf_token = csrf_token(r.path)
|
|
||||||
# render do
|
|
||||||
# form(method: "post") do
|
|
||||||
# input(type: "hidden", name: "_csrf", value: @csrf_token)
|
|
||||||
# label(for: "name")
|
|
||||||
# input(type: "text", name: "name", id: "name", required: true)
|
|
||||||
# input(type: "submit", value: "Create")
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
end
|
|
||||||
|
|
||||||
r.post do
|
|
||||||
pool = Models::Pool.create(name: r.params.fetch("name"))
|
|
||||||
r.redirect "/pools/#{pool.id}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
r.is Integer do |id|
|
|
||||||
pool = Models::Pool[id]
|
|
||||||
render do
|
|
||||||
h2 { pool.name }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,6 +1,6 @@
|
|||||||
require "roda"
|
require "roda"
|
||||||
|
|
||||||
require_relative "db"
|
require_relative "rank_king"
|
||||||
|
|
||||||
module RankKing
|
module RankKing
|
||||||
class Web < Roda
|
class Web < Roda
|
@ -0,0 +1,23 @@
|
|||||||
|
require "minitest"
|
||||||
|
|
||||||
|
require "rank_king"
|
||||||
|
|
||||||
|
class TestRankKing < Minitest::Test
|
||||||
|
def setup
|
||||||
|
@pool = Pool.create(name: "pool")
|
||||||
|
@axis = Axis.create(pool: @pool, name: "axis")
|
||||||
|
@items = (?a..?d).map { Item.create(pool: @pool, title: _1) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_rank_king
|
||||||
|
ratings = @pool.items.map {|item| Rating.first(axis: @axis, item:) || OS.rating }
|
||||||
|
original_sigma_sq = Math.sqrt(ratings.sum { _1.sigma ** 2 })
|
||||||
|
|
||||||
|
game = RankKing.suggest_game(@axis)
|
||||||
|
winner, loser = game.shuffle
|
||||||
|
RankKing.rank(@axis, winner:, loser:)
|
||||||
|
|
||||||
|
sigma_sq = Math.sqrt(@axis.ratings.sum { _1.sigma ** 2 })
|
||||||
|
assert original_sigma_sq > sigma_sq
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in new issue