12 Commits

Author SHA1 Message Date
d526fa30f4 Updated Test and Result views/routes to use BenchmarkProfile
All checks were successful
ci/woodpecker/manual/woodpecker Pipeline was successful
2026-04-15 13:58:44 -04:00
3dbc11d294 Updated development Dockerfile and entrypoint per Gemini's recommendations 2026-04-13 11:43:56 -04:00
Gregory Ballantine
b19c95187b [Issue #16] - Abstracted benchmarks from tests via BenchmarkProfile model, to allow for linking benchmarks with different runtime settings
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-09-11 16:09:00 -04:00
a736113abd Set links to use a transition for color changes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-08-28 15:22:18 -04:00
9c9b038ef8 Changing woodpecker config to create the DB right before tests
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-08-20 23:17:38 -04:00
85749a4616 Changing woodpecker config to create the DB right before tests
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-08-20 22:57:04 -04:00
619c122769 Adding more unit tests
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-08-20 22:54:23 -04:00
8c5f510c70 Added some more unit tests
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-08-20 10:34:41 -04:00
8b2c152803 Added some Content-Type unit tests
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-08-19 19:15:37 -04:00
98717db3d5 Added project logo to the README
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-08-14 09:35:43 -04:00
5d249eb3c7 Added AI-generated logo/favicon; adjusted some navbar styles
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-08-14 09:28:59 -04:00
4ed915a2c0 Added some basic table sorting
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-08-13 23:20:42 -04:00
31 changed files with 549 additions and 58 deletions

3
.gitignore vendored
View File

@@ -63,8 +63,7 @@ data/
node_modules/
# Compiled assets
public/css/
public/js/
public/*/
# Ignore production configuration files to protect against credential leaks
config/production.yaml

View File

@@ -7,7 +7,7 @@ steps:
- gem install rake
- bundle config set --local path "vendor/bundle"
- bundle install
- rake db:migrate
- RACK_ENV=testing rake db:migrate
test_ruby34:
image: ruby:3.4

View File

@@ -1,16 +1,27 @@
FROM ruby:3.4
FROM ruby:3.4-slim
RUN gem install bundler
# 1. Install essential build tools for gems like 'pg' or 'sqlite3'
RUN apt-get update -qq && apt-get install -y \
build-essential \
libpq-dev \
curl \
git
WORKDIR /usr/src/game-data
COPY Gemfile Gemfile.l*ck ./
# 2. Set environment variables for the Gem volume we discussed
ENV BUNDLE_PATH=/usr/local/bundle \
BUNDLE_BIN=/usr/local/bundle/bin \
PATH=/usr/local/bundle/bin:$PATH
RUN bundle check || bundle install
RUN gem install rake
# 3. Copy Gemfile first to leverage layer caching
COPY Gemfile Gemfile.lock ./
RUN bundle install
# 4. Copy the application code
COPY . ./
ENTRYPOINT ["bash", "entrypoints/dev.sh"]
# 5. Make sure your entrypoint script is executable
RUN chmod +x entrypoints/dev.sh
ENTRYPOINT ["bash", "entrypoints/dev.sh"]

View File

@@ -1,7 +1,9 @@
# Game Data
![Game Data Logo](https://git.metaunix.net/BitGoblin/game-data/raw/branch/main/assets/img/app-logo.png)
![Build badge](https://builds.metaunix.net/api/badges/84/status.svg)
# Game Data
Web-based tool to store and organize PC hardware gaming benchmarks.
## Project Goals

BIN
assets/img/app-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
assets/img/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1008 KiB

View File

@@ -1,7 +1,34 @@
$ ->
# run foundation scripts
# let us know when javascript is running.
console.log('Ready.')
lastColumn = null
ascending = true
tableHeaders = $('th')
tableHeaders.click (e) ->
column = $(this).index()
table = $(this).closest('table')
if column is lastColumn
ascending = not ascending
else
ascending = true
lastColumn = column
sortTable(table, column, ascending)
sortTable = (table, column, ascending) ->
rows = table.find('tbody tr').get()
compareFunction = (a, b) ->
res = a.cells[column].textContent.localeCompare b.cells[column].textContent
if ascending then res else -res
rows.sort compareFunction
$(rows).detach().appendTo(table.find('tbody'))
return
averageResults = (results, decimals = 2) ->
avgScore = 0
minScore = Infinity

View File

@@ -14,8 +14,20 @@ body
table
border: 1px solid #666
a
transition: color 220ms ease-in-out
#wrapper
background: white
padding: 1.5rem 2rem
border: 1px solid #bbb
border-radius: 8px
#main-nav
li
a
font-size: 1.25rem
#site-title
img
max-height: 40px

View File

@@ -0,0 +1,97 @@
Sequel.migration do
up do
# 1. Create benchmark_profiles
create_table(:benchmark_profiles) do
primary_key :id
String :label, null: false
String :settings, null: false
foreign_key :benchmark_id, :benchmarks, null: false, on_delete: :cascade
DateTime :created_at, default: Sequel::CURRENT_TIMESTAMP
DateTime :updated_at, default: Sequel::CURRENT_TIMESTAMP
end
# 2. Create join table (tests <-> benchmark_profiles)
create_table(:benchmark_profiles_tests) do
primary_key :id
foreign_key :test_id, :tests, null: false, on_delete: :cascade
foreign_key :benchmark_profile_id, :benchmark_profiles, null: false, on_delete: :cascade
index [:test_id, :benchmark_profile_id], unique: true
end
# 3. Add benchmark_profile_id to results
alter_table(:results) do
add_foreign_key :benchmark_profile_id, :benchmark_profiles, null: true, on_delete: :cascade
end
# 4. Migrate data from old schema
from(:benchmarks).each do |b_row|
# Create a BenchmarkProfile for this (test, benchmark) pair
bp_id = self[:benchmark_profiles].insert(
benchmark_id: b_row[:id],
label: 'Default',
settings: '{}'
)
from(:benchmarks_tests).each do |bt_row|
if bt_row[:benchmark_id] == b_row[:id]
# Link it to the test
self[:benchmark_profiles_tests].insert(
test_id: bt_row[:test_id],
benchmark_profile_id: bp_id
)
# Update results belonging to this test + benchmark pair
self[:results]
.where(test_id: bt_row[:test_id], benchmark_id: bt_row[:benchmark_id])
.update(benchmark_profile_id: bp_id)
end
end
end
# 5. Clean up old schema
alter_table(:results) do
drop_foreign_key :benchmark_id
end
drop_table(:benchmarks_tests)
end
down do
# 1. Recreate old join table
create_table(:benchmarks_tests) do
foreign_key :test_id, :tests, null: false
foreign_key :benchmark_id, :benchmarks, null: false
end
# 2. Add benchmark_id back to results
alter_table(:results) do
add_foreign_key :benchmark_id, :benchmarks, null: true
end
# 3. Restore data
from(:benchmark_profiles_tests).each do |bpt_row|
bp = self[:benchmark_profiles][id: bpt_row[:benchmark_profile_id]]
next unless bp # safety check
# Recreate old benchmarks_tests entry
self[:benchmarks_tests].insert(
test_id: bpt_row[:test_id],
benchmark_id: bp[:benchmark_id]
)
# Update results to point back to benchmark_id
self[:results]
.where(test_id: bpt_row[:test_id], benchmark_profile_id: bp[:id])
.update(benchmark_id: bp[:benchmark_id])
end
# 4. Remove new schema
alter_table(:results) do
drop_foreign_key :benchmark_profile_id
end
drop_table(:benchmark_profiles_tests)
drop_table(:benchmark_profiles)
end
end

View File

@@ -1,7 +1,9 @@
#!/bin/bash
if [ ! -f ./data/gamedata.db ]; then
rake db:migrate
fi
# Run the migrations to make sure the DB is up-to-date
echo 'Checking database status...'
rake db:migrate
# Start the HTTP server
echo 'Starting development server...'
rake server:dev

View File

@@ -20,16 +20,23 @@ function compileCoffee() {
.pipe(gulp.dest('public/js', { sourcemaps: '.' }));
}
// Copy image files to public/img/
function copyImages() {
return gulp.src('assets/img/**/*', {encoding: false})
.pipe(gulp.dest('public/img/'));
}
// Watch files for changes
function watchFiles(cb) {
gulp.watch('assets/styles/**/*.sass', compileSass);
gulp.watch('assets/scripts/**/*.coffee', compileCoffee);
gulp.watch('assets/img/**/*', copyImages)
cb();
}
// Chain all asset builds together
function buildAssets() {
return gulp.parallel(compileSass, compileCoffee);
return gulp.parallel(compileSass, compileCoffee, copyImages);
}
// Perform initial build then watch

View File

@@ -1,22 +1,27 @@
# frozen_string_literal: true
require_relative '../spec_helper'
require_relative '../../src/models/benchmark'
RSpec.describe(BenchmarkController) do
# /benchmark - redirects to /benchmark/list
# GET /benchmark - redirects to /benchmark/list
describe 'GET /benchmark' do
before { get '/benchmark' }
it 'Benchmark base route is a redirect' do
it 'Benchmark base route is a redirect.' do
expect(last_response).to(be_redirect)
end
it 'Benchmark base route is an HTML response.' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it 'Benchmark base route Location header points to /benchmark/list' do
expect(last_response['Location']).to(eq("#{BASE_URL}/benchmark/list"))
end
end
# /benchmark/list - displays a table of benchmarks
# GET /benchmark/list - displays a table of benchmarks
describe 'GET /benchmark/list' do
before { get '/benchmark/list' }
@@ -24,12 +29,16 @@ RSpec.describe(BenchmarkController) do
expect(last_response).to(be_ok)
end
it 'Benchmark list page is an HTML response.' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it "Benchmark list page contains 'List of benchmarks' on page." do
expect(last_response.body).to(include('List of benchmarks'))
end
end
# /benchmark/add - form for adding benchmark
# GET /benchmark/add - form for adding benchmark
describe 'GET /benchmark/add' do
before { get '/benchmark/add' }
@@ -37,8 +46,92 @@ RSpec.describe(BenchmarkController) do
expect(last_response).to(be_ok)
end
it 'Benchmark add page is an HTML response.' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it "Benchmark add page contains 'Add new benchmark' on page." do
expect(last_response.body).to(include('Add new benchmark'))
end
end
# POST /benchmark/add - backend for adding a benchmark
describe 'POST /benchmark/add' do
before do
request_data = {
benchmark_name: 'Test Benchmark',
benchmark_scoring: 'fps',
benchmark_description: 'Benchmark for testing'
}
post '/benchmark/add', request_data
end
it 'Benchmark add POST route is a redirect.' do
expect(last_response).to(be_redirect)
end
it 'Benchmark add POST route is an HTML response.' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it 'Benchmark add POST route Location header points to /benchmark/1' do
expect(last_response['Location']).to(eq("#{BASE_URL}/benchmark/1"))
end
it 'Benchmark add POST route creates new Benchmark.' do
expect(Benchmark.count).to(eq(1))
end
it 'Benchmark add POST route created benchmark has name.' do
expect(Benchmark.first.name).to(eq('Test Benchmark'))
end
it 'Benchmark add POST route created benchmark has scoring type.' do
expect(Benchmark.first.scoring).to(eq('fps'))
end
it 'Benchmark add POST route created benchmark has description.' do
expect(Benchmark.first.description).to(eq('Benchmark for testing'))
end
end
# GET /benchmark/:benchmark_id - page for viewing a benchmark model
describe 'GET /benchmark/:benchmark_id' do
before do
@benchmark = Benchmark.create(name: 'Test Benchmark', scoring: 'fps')
get "/benchmark/#{@benchmark.id}"
end
it 'Benchmark view page returns 200.' do
expect(last_response).to(be_ok)
end
it 'Benchmark view page is an HTML response' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it 'Benchmark view page contains "Add new benchmark" on page.' do
expect(last_response.body).to(include("#{@benchmark.name}"))
end
end
# GET /benchmark/:benchmark_id/edit - page for editing a benchmark model
describe 'GET /benchmark/:benchmark_id/edit' do
before do
@benchmark = Benchmark.create(name: 'Test Benchmark', scoring: 'fps')
get "/benchmark/#{@benchmark.id}/edit"
end
it 'Benchmark edit page returns 200.' do
expect(last_response).to(be_ok)
end
it 'Benchmark edit page is an HTML response' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it 'Benchmark edit page contains "Editing: <benchmark name>" on page.' do
expect(last_response.body).to(include("Editing: #{@benchmark.name}"))
end
end
end

View File

@@ -1,9 +1,10 @@
# frozen_string_literal: true
require_relative '../spec_helper'
require_relative '../../src/models/hardware'
RSpec.describe(HardwareController) do
# /hardware - redirects to /hardware/list
# GET /hardware - redirects to /hardware/list
describe 'GET /hardware' do
before { get '/hardware' }
@@ -11,12 +12,16 @@ RSpec.describe(HardwareController) do
expect(last_response).to(be_redirect)
end
it 'Hardware base route is an HTML response' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it 'Hardware base route Location header points to /hardware/list' do
expect(last_response['Location']).to(eq("#{BASE_URL}/hardware/list"))
end
end
# /hardware/list - displays a table of hardwares
# GET /hardware/list - displays a table of hardwares
describe 'GET /hardware/list' do
before { get '/hardware/list' }
@@ -24,12 +29,16 @@ RSpec.describe(HardwareController) do
expect(last_response).to(be_ok)
end
it 'Hardware list page is an HTML response' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it "Hardware list page contains 'List of hardware' on page." do
expect(last_response.body).to(include('List of hardware'))
end
end
# /hardware/add - form for adding hardware
# GET /hardware/add - form for adding hardware
describe 'GET /hardware/add' do
before { get '/hardware/add' }
@@ -37,8 +46,87 @@ RSpec.describe(HardwareController) do
expect(last_response).to(be_ok)
end
it 'Hardware add page is an HTML response' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it "Hardware add page contains 'Add new hardware' on page." do
expect(last_response.body).to(include('Add new hardware'))
end
end
# POST /hardware/add - backend for adding a hardware component
describe 'POST /hardware/add' do
before do
request_data = {
hardware_name: 'Test Hardware',
hardware_type: 'gpu'
}
post '/hardware/add', request_data
end
it 'Hardware add POST route is a redirect.' do
expect(last_response).to(be_redirect)
end
it 'Hardware add POST route is an HTML response.' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it 'Hardware add POST route Location header points to /hardware/1' do
expect(last_response['Location']).to(eq("#{BASE_URL}/hardware/1"))
end
it 'Hardware add POST route creates new Hardware.' do
expect(Hardware.count).to(eq(1))
end
it 'Hardware add POST route created hardware has name.' do
expect(Hardware.first.name).to(eq('Test Hardware'))
end
it 'Hardware add POST route created hardware has type.' do
expect(Hardware.first.type).to(eq('gpu'))
end
end
# GET /hardware/:hardware_id - page for viewing a hardware model
describe 'GET /hardware/:hardware_id' do
before do
@hardware = Hardware.create(name: 'Test Hardware', type: 'gpu')
get "/hardware/#{@hardware.id}"
end
it 'Hardware view page returns 200.' do
expect(last_response).to(be_ok)
end
it 'Hardware view page is an HTML response' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it 'Hardware view page contains "Add new hardware" on page.' do
expect(last_response.body).to(include("#{@hardware.name}"))
end
end
# GET /hardware/:hardware_id/edit - page for editing a hardware model
describe 'GET /hardware/:hardware_id/edit' do
before do
@hardware = Hardware.create(name: 'Test Hardware', type: 'gpu')
get "/hardware/#{@hardware.id}/edit"
end
it 'Hardware edit page returns 200.' do
expect(last_response).to(be_ok)
end
it 'Hardware edit page is an HTML response' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it 'Hardware edit page contains "Editing: <hardware name>" on page.' do
expect(last_response.body).to(include("Editing: #{@hardware.name}"))
end
end
end

View File

@@ -10,6 +10,10 @@ RSpec.describe(IndexController) do
expect(last_response).to(be_ok)
end
it 'Dashboard is an HTML response' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it "Dashboard contains 'Game Data' on page (nav bar should be loaded)." do
expect(last_response.body).to(include('Game Data'))
end

View File

@@ -10,7 +10,11 @@ RSpec.describe(ReportsController) do
expect(last_response).to(be_ok)
end
it "Reports page contains 'Generate report' on page." do
it 'Reports page is an HTML response' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it 'Reports page contains "Generate report" on page.' do
expect(last_response.body).to(include('Generate report'))
end
end

View File

@@ -3,7 +3,7 @@
require_relative '../spec_helper'
RSpec.describe(TestController) do
# /test - redirects to /test/list
# GET /test - redirects to /test/list
describe 'GET /test' do
before { get '/test' }
@@ -11,12 +11,16 @@ RSpec.describe(TestController) do
expect(last_response).to(be_redirect)
end
it 'Test base route is an HTML response' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it 'Test base route Location header points to /test/list' do
expect(last_response['Location']).to(eq("#{BASE_URL}/test/list"))
end
end
# /test/list - displays a table of tests
# GET /test/list - displays a table of tests
describe 'GET /test/list' do
before { get '/test/list' }
@@ -24,12 +28,16 @@ RSpec.describe(TestController) do
expect(last_response).to(be_ok)
end
it 'Test list page is an HTML response' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it "Test list page contains 'List of tests' on page." do
expect(last_response.body).to(include('List of tests'))
end
end
# /test/add - form for adding test
# GET /test/add - form for adding test
describe 'GET /test/add' do
before { get '/test/add' }
@@ -37,8 +45,121 @@ RSpec.describe(TestController) do
expect(last_response).to(be_ok)
end
it 'Test add page is an HTML response' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it "Test add page contains 'Add new test' on page." do
expect(last_response.body).to(include('Add new test'))
end
end
# POST /test/add - backend for adding a test
describe 'POST /test/add' do
before do
@hardware = Hardware.create(name: 'Test Hardware', type: 'gpu')
@benchmark = Benchmark.create(name: 'Test Benchmark', scoring: 'fps')
request_data = {
test_name: 'Test Test',
test_hardware: @hardware.id,
'test_benchmarks[]': [@benchmark.id],
test_description: 'Test for testing'
}
post '/test/add', request_data
end
it 'Test add POST route is a redirect.' do
expect(last_response).to(be_redirect)
end
it 'Test add POST route is an HTML response.' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it 'Test add POST route Location header points to /test/1' do
expect(last_response['Location']).to(eq("#{BASE_URL}/test/1"))
end
it 'Test add POST route creates new Test.' do
expect(Test.count).to(eq(1))
end
it 'Test add POST route created test has name.' do
expect(Test.first.name).to(eq('Test Test'))
end
it 'Test add POST route created test has hardware.' do
expect(Test.first.hardware.id).to(eq(@hardware.id))
end
it 'Test add POST route created test has benchmarks.' do
expect(Test.first.benchmarks.length).to(eq(1))
end
it 'Test add POST route created test\'s benchmark can be read.' do
expect(Test.first.benchmarks[0].id).to(eq(@benchmark.id))
end
it 'Test add POST route created test has description.' do
expect(Test.first.description).to(eq('Test for testing'))
end
end
# GET /test/:test_id - page for viewing a test model
describe 'GET /test/:test_id' do
before do
@hardware = Hardware.create(name: 'Test Hardware', type: 'gpu')
@benchmark = Benchmark.create(name: 'Test Benchmark', scoring: 'fps')
@test = Test.create(
name: 'Test Test',
hardware_id: @hardware.id,
description: 'Test for testing'
)
@test.add_benchmark(@benchmark)
get "/test/#{@test.id}"
end
it 'Test view page returns 200.' do
expect(last_response).to(be_ok)
end
it 'Test view page is an HTML response' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it 'Test view page contains test name on page.' do
expect(last_response.body).to(include("#{@test.name}"))
end
it 'Test view page contains hardware name on page.' do
expect(last_response.body).to(include("#{@hardware.name}"))
end
end
# GET /test/:test_id/edit - page for editing a test model
describe 'GET /test/:test_id/edit' do
before do
@hardware = Hardware.create(name: 'Test Hardware', type: 'gpu')
@benchmark = Benchmark.create(name: 'Test Benchmark', scoring: 'fps')
@test = Test.create(
name: 'Test Test',
hardware_id: @hardware.id,
description: 'Test for testing'
)
@test.add_benchmark(@benchmark)
get "/test/#{@test.id}/edit"
end
it 'Test edit page returns 200.' do
expect(last_response).to(be_ok)
end
it 'Test edit page is an HTML response' do
expect(last_response['Content-Type']).to(include('text/html'))
end
it 'Test edit page contains "Editing: <test name>" on page.' do
expect(last_response.body).to(include("Editing: #{@test.name}"))
end
end
end

View File

@@ -2,6 +2,7 @@
require_relative 'base_controller'
require_relative '../models/test'
require_relative '../models/benchmark_profile'
# / (top-level) routes
class IndexController < BaseController

View File

@@ -12,7 +12,7 @@ class ResultController < BaseController
Result.create(
test_id: params[:result_test],
benchmark_id: params[:result_benchmark],
benchmark_profile_id: params[:result_benchmark],
avg_score: params[:result_average],
min_score: result_minimum,
max_score: result_maximum

View File

@@ -42,7 +42,7 @@ class TestController < BaseController
benchmarks = Array(params[:test_benchmarks])
# associate the benchmarks to the test
benchmarks.each do |b|
tst.add_benchmark(b)
tst.add_benchmark_profile(b)
end
redirect "/test/#{tst.id}"
@@ -81,13 +81,13 @@ class TestController < BaseController
selected_benchmarks = Array(params[:test_benchmarks])
# remove benchmarks no longer associated with the test
tst.benchmarks.dup.each do |b|
tst.remove_benchmark(b.id) unless selected_benchmarks.include?(b.id)
tst.benchmark_profiles.dup.each do |b|
tst.remove_benchmark_profile(b.id) unless selected_benchmarks.include?(b.id)
end
# associate the benchmarks to the test
selected_benchmarks.each do |b|
tst.add_benchmark(b) unless tst.benchmark?(b)
tst.add_benchmark_profile(b) unless tst.benchmark?(b)
end
redirect "/test/#{tst.id}"

View File

@@ -3,7 +3,6 @@
# Benchmark - database model for PC benchmarks
class Benchmark < Sequel::Model
many_to_many :tests
one_to_many :results
one_to_many :benchmark_profiles
end

View File

@@ -0,0 +1,14 @@
# frozen_string_literal: true
# BenchmarkProfile - database model for benchmark settings profile
class BenchmarkProfile < Sequel::Model
many_to_one :benchmark
many_to_many :tests
one_to_many :results
def display_name
"#{benchmark.name} @ #{label}"
end
end

View File

@@ -4,7 +4,7 @@
class Result < Sequel::Model
many_to_one :test
many_to_one :benchmark
many_to_one :benchmark_profile
def formatted_score
return @avg_score

View File

@@ -5,10 +5,10 @@ class Test < Sequel::Model
one_to_many :result
many_to_one :hardware
many_to_many :benchmarks
many_to_many :benchmark_profiles
def benchmark?(benchmark_id)
return benchmarks_dataset.where(Sequel[:benchmarks][:id] => benchmark_id).any?
return benchmark_profiles_dataset.where(Sequel[:benchmark_profiles][:id] => benchmark_id).any?
end
end

View File

@@ -21,29 +21,31 @@
<div class="row">
<div class="col-12">
<h3 class="mb-3">Tests using this benchmark:</h3>
<h3 class="mb-3">Profiles created for this benchmark:</h3>
<% if benchmark.tests.length > 0 %>
<% if benchmark.benchmark_profiles.length > 0 %>
<table class="table table-hover table-responsive">
<thead class="table-light">
<tr>
<th>Test title</th>
<th>Benchmarks</th>
<th>Profile Label</th>
<th>Tests Linked</th>
<th>Created at</th>
<th>Last updated</th>
</tr>
</thead>
<tbody>
<% benchmark.tests.each do |t| %>
<% benchmark.benchmark_profiles.each do |bp| %>
<tr>
<td><a href="/test/<%= t.id %>"><%= t.name %></a></td>
<td><%= t.benchmarks.length %></td>
<td><%= t.updated_at %></td>
<td><%= bp.display_name %></td>
<td><%= bp.tests.length %></td>
<td><%= bp.created_at %></td>
<td><%= bp.updated_at %></td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<p>There are no tests associated with this benchmark.</p>
<p>There are no profiles associated with this benchmark.</p>
<% end %>
</div>
</div>

View File

@@ -8,16 +8,16 @@
<table class="table table-hover table-responsive">
<thead class="table-light">
<tr>
<th>Test name</th>
<th># Benchmarks</th>
<th>Last Updated</th>
<th data-sort="name">Test name</th>
<th data-sort="benchmark-count"># Benchmarks</th>
<th data-sort="updated'">Last Updated</th>
</tr>
</thead>
<tbody>
<% tests.each do |t| %>
<tr>
<td><a href="/test/<%= t.id %>"><%= t.name %></a></td>
<td><%= t.benchmarks.length %></td>
<td><%= t.benchmark_profiles.length %></td>
<td><%= t.updated_at %></td>
</tr>
<% end %>

View File

@@ -4,6 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="shortcut icon" href="/img/favicon.png">
<title><%= title %> | Game Data</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/rimmington.css">

View File

@@ -1,6 +1,9 @@
<div id="main-nav" class="navbar navbar-expand-md bg-dark border-bottom border-body mb-3" data-bs-theme="dark">
<div class="container-fluid">
<a class="navbar-brand mb-0 h1" href="#">Game Data</a>
<a id="site-title" class="navbar-brand mb-0 h1" href="#">
Game Data
<img src="/img/app-logo.png" alt="">
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>

View File

@@ -28,8 +28,10 @@
<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>
<% for bp in b.benchmark_profiles %>
<option value="<%= bp.id %>"><%= bp.display_name %></option>
<% end %>
<% end %>
</select>
</div>

View File

@@ -28,8 +28,10 @@
<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 %>" <% if test.benchmark?(b.id) %>selected<% end %>><%= b.name %></option>
<% for bp in b.benchmark_profiles %>
<option value="<%= bp.id %>" <% if test.benchmark?(bp.id) %>selected<% end %>><%= bp.display_name %></option>
<% end %>
<% end %>
</select>
</div>

View File

@@ -26,7 +26,7 @@
<% tests.each do |t| %>
<tr>
<td><a href="/test/<%= t.id %>"><%= t.name %></a></td>
<td><%= t.benchmarks.length %></td>
<td><%= t.benchmark_profiles.length %></td>
<td><%= date_format(t.created_at) %></td>
<td><%= date_format(t.updated_at) %></td>
</tr>

View File

@@ -28,8 +28,8 @@
<div class="col-12 col-md-5 mb-3 mb-md-0">
<label for="result_benchmark">Add benchmark result:</label>
<select class="form-select" id="result_benchmark" name="result_benchmark">
<% test.benchmarks.each do |b| %>
<option value="<%= b.id %>"><%= b.name %></option>
<% test.benchmark_profiles.each do |b| %>
<option value="<%= b.id %>"><%= b.display_name %></option>
<% end %>
</select>
</div>
@@ -71,8 +71,8 @@
</tr>
</thead>
<tbody>
<% test.benchmarks.each do |benchmark| %>
<tr data-benchmark-id="<%= benchmark.id %>"></tr>
<% test.benchmark_profiles.each do |bp| %>
<tr data-benchmark-id="<%= bp.id %>"></tr>
<% end %>
</tbody>
</table>