Compare commits

..

9 Commits

Author SHA1 Message Date
25d394627d Version bump to v0.1.1
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2025-07-28 11:01:35 -04:00
85dfdb163a Fixed rubocop warnings
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-07-28 10:57:40 -04:00
b593ef7593 Updating to ruby:3.4 in CI/CD
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-07-28 10:54:53 -04:00
26698082f4 Removed backup copy of the reports.coffee script
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2025-07-28 10:49:09 -04:00
42a0b95015 Fixed the chart generation page with the new ChartJS version and DB schema
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2025-07-28 10:48:49 -04:00
5cc3b8f824 Added a better way of setting/reading the app version; fixed some of the flexbox sizing
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2025-07-28 10:23:51 -04:00
d59c75281e Updating puma.rb to allow changing the rack environment dynamically
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2025-07-28 10:17:45 -04:00
55e4f397f8 Fixed the test edit view
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2025-07-26 11:37:43 -04:00
49d1276031 Fixed puma config for new Puma versions 2025-07-26 11:32:32 -04:00
17 changed files with 213 additions and 111 deletions

View File

@ -1,6 +1,6 @@
pipeline: pipeline:
style: style:
image: ruby:3.0 image: ruby:3.4
commands: commands:
- 'gem install rake' - 'gem install rake'
- 'bundle config set --local path "vendor/bundle"' - 'bundle config set --local path "vendor/bundle"'

View File

@ -1,3 +1,3 @@
$ -> $ ->
# run foundation scripts # run foundation scripts
$(document).foundation() console.log('Ready.')

View File

@ -1,55 +1,113 @@
$(document).ready -> $ ->
$('#generate_button').on 'click', (e) -> chartInstance = null
e.preventDefault()
$.ajax(
method: 'POST'
url: '/reports'
data:
type: $('#report_type').val()
choice: $('#report_choice').val()
compare: $('#report_compare').val()
).done (data) ->
benchChart.options.title.text = data.choice
benchChart.data.labels = data.names
benchChart.data.datasets[0].data = data.avg_results
benchChart.data.datasets[1].data = data.min_results
benchChart.update()
return
return
return
benchChart = new Chart(document.getElementById('chart_canvas').getContext('2d'), $('#reports-download').on 'click', (e) ->
type: 'horizontalBar' e.preventDefault()
data: canvas = $('#benchmark-chart')[0]
labels: [] a = document.createElement 'a'
datasets: [ a.href = canvas.toDataURL 'image/png'
{ a.download = 'chart.png'
label: 'Average FPS' a.click()
data: []
backgroundColor: 'hotpink' $('#reports-button').on 'click', (e) ->
borderColor: '#212121' e.preventDefault()
borderWidth: 1 $('#reports-download').attr('disabled', true)
} chartInstance.destroy() if chartInstance
{
label: 'Minimum FPS' benchmarkId = $('#report-benchmarks').val()
data: [] testIds = $('#report-tests').val()
backgroundColor: 'cornflowerblue'
borderColor: '#212121' benchmarkSearchParams = new URLSearchParams
borderWidth: 1 benchmark_id: benchmarkId
} benchmarkRes = await fetch("/api/v1/benchmark/details?#{benchmarkSearchParams}")
] benchmarkData = await benchmarkRes.json()
options:
title: data =
display: true labels: []
text: 'N/a' datasets: []
scales: xAxes: [ {
display: true switch benchmarkData.scoring
ticks: beginAtZero: true when 'pts'
} ] data.datasets.push({
animation: onComplete: -> label: 'Average Score'
dwnbtn = $('#download_button') data: []
dwnbtn.attr 'href', benchChart.toBase64Image() })
dwnbtn.attr 'download', 'benchmark_chart.png' when 'fps'
dwnbtn.attr 'disabled', false data.datasets.push({
return label: 'Average FPS'
) data: []
})
data.datasets.push({
label: 'Minimum FPS'
data: []
})
when 'ms'
data.datasets.push({
label: 'Average Frame Time'
data: []
})
data.datasets.push({
label: 'Minimum Frame Time'
data: []
})
for testId in testIds
try
testSearchParams = new URLSearchParams
test_id: testId
testRes = await fetch("/api/v1/test/details?#{testSearchParams}")
testData = await testRes.json()
resultSearchParams = new URLSearchParams
test_id: testId
benchmark_id: benchmarkId
resultRes = await fetch("/api/v1/result/list?#{resultSearchParams}")
resultData = await resultRes.json()
avg_total = 0
min_total = 0
max_total = 0
for result in resultData
avg_total += result.avg_score
min_total += result.min_score if result.min_score
max_total += result.max_score if result.max_score
data.labels.push(testData.name)
data.datasets[0].data.push(avg_total / resultData.length)
console.log(data.datasets[0].data)
switch benchmarkData.scoring
when 'fps', 'ms'
data.datasets[1].data.push(min_total / resultData.length)
catch error
console.error 'An error occurred while fetching benchmark results.', error
ctx = $('#benchmark-chart')[0].getContext('2d')
options =
indexAxis: 'y'
plugins:
title:
display: true
text: benchmarkData.name
font:
size: '24'
datalabels:
anchor: 'end'
align: 'left'
color: 'black'
font:
weight: 'bold'
formatter: (value) -> value
scales:
y:
beginAtZero: true
chartInstance = new Chart ctx,
type: 'bar'
data: data
options: options
plugins: [ChartDataLabels]
$('#reports-download').attr('disabled', false)
$('#benchmark-chart').removeClass('disabled')

View File

@ -10,7 +10,7 @@ fetchTestBenchmarkResults = (testId, benchmarkId) ->
resultSearchParams = new URLSearchParams resultSearchParams = new URLSearchParams
test_id: testId test_id: testId
benchmark_id: benchmarkId benchmark_id: benchmarkId
resultRes = await fetch("/api/v1/results?#{resultSearchParams}") resultRes = await fetch("/api/v1/result/list?#{resultSearchParams}")
resultData = await resultRes.json() resultData = await resultRes.json()
avg_total = 0 avg_total = 0

View File

@ -4,6 +4,10 @@
$primary-color: cornflowerblue $primary-color: cornflowerblue
$primary-color-highlight: color.adjust($primary-color, $lightness: -10%) $primary-color-highlight: color.adjust($primary-color, $lightness: -10%)
html
width: 100%
height: 100%
body body
background: rgb(240, 235, 248) background: rgb(240, 235, 248)

View File

@ -1,14 +1,9 @@
app_dir = File.expand_path("..", __dir__) app_dir = File.expand_path('..', __dir__)
log_dir = File.join(app_dir, "log")
pid_dir = "/var/run/game-data" # or use app_dir + '/tmp/pids' if not using system-wide PID dir
directory app_dir directory app_dir
pidfile File.join(pid_dir, "puma.pid")
stdout_redirect File.join(log_dir, "puma.log"), File.join(log_dir, "puma.err.log"), true
environment 'production' environment ENV.fetch('RACK_ENV', 'development')
bind 'tcp://0.0.0.0:9292' bind 'tcp://0.0.0.0:9292'
workers 2 workers 2
threads 1, 5 threads 1, 5
daemonize true

7
src/appinfo.rb Normal file
View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
module AppInfo
VERSION = '0.1.1'
end

View File

@ -3,12 +3,12 @@
# Helpers - view helper functions # Helpers - view helper functions
module Helpers module Helpers
def ruby_version() def ruby_version
return RUBY_VERSION return RUBY_VERSION
end end
def app_version() def app_version
`git describe --tags`.strip return AppInfo::VERSION
end end
def date_format(date) def date_format(date)

View File

@ -11,7 +11,7 @@ class GameData < Sinatra::Base
json benchmark.values() json benchmark.values()
end end
get '/api/v1/results' do get '/api/v1/result/list' do
test_id = params[:test_id] test_id = params[:test_id]
benchmark_id = params[:benchmark_id] benchmark_id = params[:benchmark_id]
@ -20,4 +20,12 @@ class GameData < Sinatra::Base
json results.map(&:values) json results.map(&:values)
end end
get '/api/v1/test/details' do
test_id = params[:test_id]
tst = Test.where(id: test_id).first()
json tst.values()
end
end end

View File

@ -15,6 +15,7 @@ class GameData < Sinatra::Base
get '/test/add' do get '/test/add' do
hardware = Hardware.order(:name).all() hardware = Hardware.order(:name).all()
benchmarks = Benchmark.order(:name).all() benchmarks = Benchmark.order(:name).all()
erb :'test/add', locals: { erb :'test/add', locals: {
title: 'Add Test', title: 'Add Test',
hardware: hardware, hardware: hardware,
@ -46,23 +47,28 @@ class GameData < Sinatra::Base
} }
end end
get '/test/:hardware_id/edit' do get '/test/:test_id/edit' do
hardware = Hardware.where(id: params[:hardware_id]).first() tst = Test.where(id: params[:test_id]).first()
hardware = Hardware.order(:name).all()
benchmarks = Benchmark.order(:name).all()
erb :'test/edit', locals: { erb :'test/edit', locals: {
title: "Editing: #{hardware.name}", title: "Editing: #{tst.name}",
hardware: hardware test: tst,
hardware: hardware,
benchmarks: benchmarks
} }
end end
post '/test/:hardware_id/edit' do post '/test/:test_id/edit' do
hardware = Hardware.where(id: params[:hardware_id]).first() tst = Test.where(id: params[:test_id]).first()
hardware.update( tst.update(
name: params[:hardware_name], name: params[:test_name],
type: params[:hardware_type] type: params[:test_type]
) )
redirect "/hardware/#{hardware.id}" redirect "/test/#{tst.id}"
end end
end end

View File

@ -5,6 +5,8 @@ require 'sinatra/json'
require 'sequel' require 'sequel'
require 'sqlite3' require 'sqlite3'
require_relative 'appinfo'
# Load the Sequel timestamps plugin # Load the Sequel timestamps plugin
Sequel::Model.plugin(:timestamps) Sequel::Model.plugin(:timestamps)
# Initialize Sequel gem for database actions # Initialize Sequel gem for database actions

View File

@ -17,7 +17,7 @@
<% tests.each do |t| %> <% tests.each do |t| %>
<tr> <tr>
<td><a href="/test/<%= t.id %>"><%= t.name %></a></td> <td><a href="/test/<%= t.id %>"><%= t.name %></a></td>
<td><%= t.benchmark.length %></td> <td><%= t.benchmarks.length %></td>
<td><%= t.updated_at %></td> <td><%= t.updated_at %></td>
</tr> </tr>
<% end %> <% end %>

View File

@ -10,16 +10,17 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" charset="utf-8"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.7/js/bootstrap.min.js" charset="utf-8"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.7/js/bootstrap.min.js" charset="utf-8"></script>
<script src="/js/edgeville.js" charset="utf-8"></script> <script src="/js/edgeville.js" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js" charset="utf-8"></script>
</head> </head>
<body> <body class="d-flex flex-column min-vh-100">
<!-- main navigation --> <!-- main navigation -->
<%= erb :'partials/navbar', :locals => locals %> <%= erb :'partials/navbar', :locals => locals %>
<!-- main content --> <!-- main content -->
<div id="wrapper" class="container mb-4"> <main class="flex-grow-1 py-4">
<%= yield %> <div id="wrapper" class="container mb-4">
</div> <%= yield %>
</div>
</main>
<!-- site footer --> <!-- site footer -->
<%= erb :'partials/footer', :locals => locals %> <%= erb :'partials/footer', :locals => locals %>

View File

@ -1,8 +1,10 @@
<nav id="main-footer" class="container"> <footer id="main-footer" class="bg-light border-top py-3 text-center">
<div class="row"> <div class="container">
<div class="col-12"> <div class="row">
<p>Game Data version v<%= app_version() %></p> <div class="col-12">
<p>Running Ruby version v<%= ruby_version() %></p> <p>Game Data version v<%= app_version() %></p>
<p class="mb-0">Running Ruby version v<%= ruby_version() %></p>
</div>
</div> </div>
</div> </div>
</nav> </footer>

View File

@ -2,14 +2,14 @@
<form class="col-12" action="/reports" method="post"> <form class="col-12" action="/reports" method="post">
<div class="row mb-3"> <div class="row mb-3">
<div class="col-12 col-md-6"> <div class="col-12 col-md-6">
<select id="report_type" class="form-select" name="report_type" disabled> <select id="report-type" class="form-select" name="report_type" disabled>
<option value="benchmark">Benchmark</option> <option value="benchmark">Benchmark</option>
<option value="test">Test</option> <option value="test">Test</option>
</select> </select>
</div> </div>
<div class="col-12 col-md-6"> <div class="col-12 col-md-6">
<select id="report_choice" class="form-select" name="report_choice"> <select id="report-benchmarks" class="form-select" name="report_choice">
<% benchmarks.each do |b| %> <% benchmarks.each do |b| %>
<option value="<%= b.id %>"><%= b.name %></option> <option value="<%= b.id %>"><%= b.name %></option>
<% end %> <% end %>
@ -18,7 +18,7 @@
</div> </div>
<div class="col-12 mb-3"> <div class="col-12 mb-3">
<select id="report_compare" class="col-12 form-select" name="report_compare[]" multiple> <select id="report-tests" class="col-12 form-select" name="report_compare[]" multiple>
<% tests.each do |t| %> <% tests.each do |t| %>
<option value="<%= t.id %>"><%= t.name %></option> <option value="<%= t.id %>"><%= t.name %></option>
<% end %> <% end %>
@ -26,16 +26,18 @@
</div> </div>
<div class="col-12 mb-3"> <div class="col-12 mb-3">
<input type="submit" class="btn btn-primary" id="generate_button" value="Generate"> <button id="reports-button" class="btn btn-primary">Generate</button>
<a href="#" class="btn btn-primary" id="download_button" disabled>Download</a> <button id="reports-download" class="btn btn-primary" disabled>Download</button>
</div> </div>
<div class="col-12"> <div class="col-12">
<canvas id="chart_canvas" width="100%" height="25"></canvas> <canvas id="benchmark-chart" width="100%" height="25"></canvas>
</div> </div>
</form> </form>
</div> </div>
<!-- load the chart.js library --> <!-- load the chart.js library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.min.js" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.2.0/chartjs-plugin-datalabels.min.js" charset="utf-8"></script>
<!-- load chart functionality --> <!-- load chart functionality -->
<script src="/js/reports.js" charset="utf-8"></script> <script src="/js/reports.js" charset="utf-8"></script>

View File

@ -1,30 +1,47 @@
<div class="row"> <div class="row mb-3">
<div class="col-12"> <div class="col-12">
<h1>Editing: <%= hardware.name %></h1> <h1>Editing: <%= test.name %></h1>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<form class="col-12" action="/hardware/<%= hardware.id %>/edit" method="post"> <form class="col-12" action="/test/<%= test.id %>/edit" method="post">
<div class="row mb-3"> <div class="row mb-0 mb-md-3">
<div class="col-12 col-md-9"> <div class="col-12 col-md-6 mb-3 mb-md-0">
<label for="hardware_name">Hardware name</label> <label for="test_name">Test name</label>
<input id="hardware_name" class="form-control" type="text" name="hardware_name" placeholder="Example hardware" value="<%= hardware.name %>"> <input id="test_name" class="form-control" type="text" name="test_name" placeholder="My hardware test (01/99)" value="<%= test.name %>">
</div> </div>
<div class="col-12 col-md-3"> <div class="col-12 col-md-6 mb-3 mb-md-0">
<label for="hardware_type">Type</label> <label for="test_hardware">Hardware to test</label>
<select id="hardware_type" class="form-control" name="hardware_type"> <select id="test_hardware" class="form-select" name="test_hardware">
<option value="gpu" <% if hardware.type == 'gpu' %>selected<% end %>>Graphics card</option> <% for h in hardware %>
<option value="cpu" <% if hardware.type == 'cpu' %>selected<% end %>>Processor</option> <option value="<%= h.id %>" <% if h.id == test.hardware.id %>selected<% end %>><%= h.name %></option>
<% end %>
</select> </select>
</div> </div>
</div> </div>
<div class="row mb-0 mb-md-3">
<div class="col-12 col-md-4 mb-3 mb-md-0">
<label for="test_benchmarks">Benchmarks</label>
<select id="test_benchmarks" class="form-select" name="test_benchmarks[]" multiple>
<% for b in benchmarks %>
<option value="<%= b.id %>"><%= b.name %></option>
<% end %>
</select>
</div>
<div class="col-12 col-md-8 mb-3 mb-md-0">
<label for="test_description">Test description</label>
<textarea id="test_description" class="form-control" name="test_description" placeholder="This is my test for a hardware..."><%= test.description %></textarea>
</div>
</div>
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<input class="btn btn-primary w-100" type="submit" value="Submit Changes"> <input class="btn btn-primary w-100" type="submit" value="Create Test">
</div> </div>
</div> </div>
</form> </form>

View File

@ -8,7 +8,7 @@
</div> </div>
<div class="col-12"> <div class="col-12">
<p>Hardware tested: <%= test.hardware.name %></p> <p>Hardware tested: <a href="/hardware/<%= test.hardware.id %>"><%= test.hardware.name %></a></p>
</div> </div>
<div class="col-12"> <div class="col-12">