12 Commits

Author SHA1 Message Date
Gregory Ballantine
886f566ae2 Started work to move the CSS framework to Bootstrap 5
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/tag/woodpecker Pipeline failed
2025-07-25 17:44:25 -04:00
Gregory Ballantine
fdd350e16f Updated gulpfile to be a little bit less repetitive
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2025-07-25 13:41:51 -04:00
bc4cb181c3 Added some styles
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2025-07-23 23:54:12 -04:00
822f49bcc2 fixed display of tests on the dashboard 2025-07-23 23:26:22 -04:00
aec77628f7 Small updates
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2025-07-23 23:25:00 -04:00
ecb696372d Added dockerfile to build assets via Gulp; updated docker scripts 2025-07-23 23:24:49 -04:00
31b8404be1 Swapping out Grunt for Gulp 2025-06-22 19:30:17 -04:00
8cd47d7e70 Added API routes to provide some information for JS; added CoffeeScript to grab benchmark results for a test 2025-06-19 00:38:36 -04:00
d17b66920a Fixed typo in watch task for CoffeeScript files 2025-06-18 16:44:10 -04:00
47cb580393 Started adding test model/routes/views; removed a bit of the old paradigm with tying results directly to hardware 2025-06-10 17:35:52 -04:00
883019b181 Fixing server:dev Rake command to actuualy reload the app 2025-06-09 23:27:48 -04:00
2cc80e239b Added TTY flag to docker-run.bat 2025-05-30 09:38:20 -04:00
49 changed files with 2875 additions and 1309 deletions

View File

@@ -2,7 +2,7 @@ FROM ruby:3.4
RUN gem install bundler
WORKDIR /src
WORKDIR /usr/src/game-data
COPY Gemfile Gemfile.l*ck ./
@@ -13,3 +13,4 @@ RUN gem install rake
COPY . ./
ENTRYPOINT ["bash", "entrypoints/dev.sh"]

13
Dockerfile.gulp Normal file
View File

@@ -0,0 +1,13 @@
# Node.js runtime
FROM node:24
WORKDIR /usr/src/game-data/
COPY package.* /usr/src/game-data/
RUN npm install
VOLUME /usr/src/game-data/node_modules/
# Run the app
CMD [ "npm", "run", "gulp" ]

View File

@@ -8,7 +8,6 @@ gem 'sequel', '~> 5.92'
gem 'sqlite3', '~> 2.6'
gem 'logger'
gem 'ostruct'
group :development, :test do
gem 'rerun'

View File

@@ -2,21 +2,29 @@ GEM
remote: https://rubygems.org/
specs:
ast (2.4.3)
base64 (0.2.0)
bigdecimal (3.2.0)
base64 (0.3.0)
bigdecimal (3.2.2)
ffi (1.17.2-aarch64-linux-gnu)
ffi (1.17.2-aarch64-linux-musl)
ffi (1.17.2-arm-linux-gnu)
ffi (1.17.2-arm-linux-musl)
ffi (1.17.2-arm64-darwin)
ffi (1.17.2-x86-linux-gnu)
ffi (1.17.2-x86-linux-musl)
ffi (1.17.2-x86_64-darwin)
ffi (1.17.2-x86_64-linux-gnu)
ffi (1.17.2-x86_64-linux-musl)
json (2.12.2)
language_server-protocol (3.17.0.5)
lint_roller (1.1.0)
listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
logger (1.6.4)
logger (1.7.0)
multi_json (1.15.0)
mustermann (3.0.3)
ruby2_keywords (~> 0.0.1)
nio4r (2.7.4)
ostruct (0.6.1)
parallel (1.27.0)
parser (3.3.8.0)
ast (~> 2.4.1)
@@ -25,7 +33,7 @@ GEM
puma (6.6.0)
nio4r (~> 2.0)
racc (1.8.1)
rack (2.2.16)
rack (2.2.17)
rack-protection (3.2.0)
base64 (>= 0.1.0)
rack (~> 2.2, >= 2.2.4)
@@ -36,7 +44,7 @@ GEM
regexp_parser (2.10.0)
rerun (0.14.0)
listen (~> 3.0)
rubocop (1.75.8)
rubocop (1.76.1)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
@@ -44,10 +52,10 @@ GEM
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.44.0, < 2.0)
rubocop-ast (>= 1.45.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.44.1)
rubocop-ast (1.45.1)
parser (>= 3.3.7.2)
prism (~> 1.4)
rubocop-sequel (0.4.1)
@@ -55,7 +63,7 @@ GEM
rubocop (>= 1.72.1, < 2)
ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5)
sequel (5.92.0)
sequel (5.93.0)
bigdecimal
sinatra (3.2.0)
mustermann (~> 3.0)
@@ -68,18 +76,35 @@ GEM
rack-protection (= 3.2.0)
sinatra (= 3.2.0)
tilt (~> 2.0)
sqlite3 (2.6.0-x86_64-linux-gnu)
sqlite3 (2.7.0-aarch64-linux-gnu)
sqlite3 (2.7.0-aarch64-linux-musl)
sqlite3 (2.7.0-arm-linux-gnu)
sqlite3 (2.7.0-arm-linux-musl)
sqlite3 (2.7.0-arm64-darwin)
sqlite3 (2.7.0-x86-linux-gnu)
sqlite3 (2.7.0-x86-linux-musl)
sqlite3 (2.7.0-x86_64-darwin)
sqlite3 (2.7.0-x86_64-linux-gnu)
sqlite3 (2.7.0-x86_64-linux-musl)
tilt (2.6.0)
unicode-display_width (3.1.4)
unicode-emoji (~> 4.0, >= 4.0.4)
unicode-emoji (4.0.4)
PLATFORMS
aarch64-linux-gnu
aarch64-linux-musl
arm-linux-gnu
arm-linux-musl
arm64-darwin
x86-linux-gnu
x86-linux-musl
x86_64-darwin
x86_64-linux-gnu
x86_64-linux-musl
DEPENDENCIES
logger
ostruct
puma (~> 6.6)
rerun
rubocop

View File

@@ -1,65 +0,0 @@
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
dist: {
options: {
style: 'compressed'
},
files: [{
expand: true,
cwd: 'assets/styles',
src: ['**/*.sass'],
dest: 'public/css',
ext: '.css'
}]
}
},
coffee: {
options: {
sourceMap: true,
style: 'compressed'
},
files: {
expand: true,
flatten: true,
cwd: 'assets/scripts',
src: ['*.coffee'],
dest: 'public/js',
ext: '.js'
}
},
watch: {
css: {
files: ['assets/styles/**/*.sass'],
tasks: ['sass'],
options: {
atBegin: true,
spawn: false
}
},
js: {
files: ['assets/scripts/**/*.js'],
tasks: ['coffee'],
options: {
atBegin: true,
spawn: false
}
}
}
});
// Load plugins.
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-coffee');
// CLI tasks.
grunt.registerTask('default', ['sass', 'coffee']);
};

View File

@@ -19,7 +19,7 @@ namespace :server do
end
task :dev do
system('rerun --no-notify --exit --dir="src/" puma')
system('rerun --no-notify --dir="src/" puma')
end
end

View File

@@ -1,2 +1,3 @@
$ ->
# run foundation scripts
$(document).foundation()

View File

@@ -7,7 +7,8 @@ $(document).ready ->
data:
type: $('#report_type').val()
choice: $('#report_choice').val()
compare: $('#report_compare').val()).done (data) ->
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

View File

@@ -0,0 +1,49 @@
testId = $('#results-table').data('test-id')
fetchTestBenchmarkResults = (testId, benchmarkId) ->
try
benchmarkSearchParams = new URLSearchParams
benchmark_id: benchmarkId
benchmarkRes = await fetch("/api/v1/benchmark/details?#{benchmarkSearchParams}")
benchmarkData = await benchmarkRes.json()
resultSearchParams = new URLSearchParams
test_id: testId
benchmark_id: benchmarkId
resultRes = await fetch("/api/v1/results?#{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
max_total += result.max_score
tableRow = $("#results-table tr[data-benchmark-id=#{benchmarkId}]")
tableRow.append('<td>' + benchmarkData.name + '</td>')
tableRow.append('<td>' + benchmarkData.scoring + '</td>')
tableRow.append('<td>' + resultData.length + '</td>')
if resultData.length != 0
tableRow.append('<td>' + (avg_total / resultData.length) + '</td>')
else
tableRow.append('<td>N/a</td>')
if min_total != 0
tableRow.append('<td>' + (min_total / resultData.length) + '</td>')
tableRow.append('<td>' + (max_total / resultData.length) + '</td>')
else
tableRow.append('<td>N/a</td>')
tableRow.append('<td>N/a</td>')
catch error
console.error 'An error occurred while fetching benchmark results.', error
$('#results-table tbody tr').each((index, tr) ->
benchmarkId = $(tr).data('benchmark-id')
console.log("Fetching results for benchmark id: " + benchmarkId)
fetchTestBenchmarkResults(testId, benchmarkId)
)

View File

@@ -1,5 +0,0 @@
#main-nav
margin-bottom: 15px
h1.invalid
color: red

View File

@@ -0,0 +1,13 @@
@use "sass:color"
//$primary-color: #3399ff
$primary-color: cornflowerblue
$primary-color-highlight: color.adjust($primary-color, $lightness: -10%)
body
background: rgb(240, 235, 248)
#wrapper
background: white
padding: 1.5rem 2rem
border-radius: 8px

View File

@@ -1 +1,2 @@
docker build -t game-data -f Dockerfile.dev .
docker build -t game-data-gulp -f Dockerfile.gulp .

View File

@@ -1,3 +1,5 @@
#!/bin/sh
docker build -t game-data -f Dockerfile.dev .
docker build -t game-data-gulp -f Dockerfile.gulp .

View File

@@ -1 +1,2 @@
docker run --rm -d -v "%cd%:/src" -p 9292:9292 --name game-data game-data
docker run --rm -d -t -v "%cd%:/usr/src/game-data" -p 9292:9292 --name game-data game-data
docker run --rm -d -t -v "%cd%:/usr/src/game-data" --name game-data-gulp game-data-gulp npm run gulp watch

View File

@@ -1,3 +1,5 @@
#!/bin/sh
docker run --rm -d -t -v "$(pwd):/src" -p 9292:9292 --name game-data game-data
docker run --rm -d -t -v "$(pwd):/usr/src/game-data" -p 9292:9292 --name game-data game-data
docker run --rm -d -t -v "$(pwd):/usr/src/game-data" --name game-data-gulp game-data-gulp npm run gulp watch

View File

@@ -0,0 +1,39 @@
Sequel.migration do
up do
# create tests table
create_table(:tests) do
primary_key :id
foreign_key :hardware_id, :hardware
String :name, null: false
String :description
DateTime :created_at, default: Sequel::CURRENT_TIMESTAMP
DateTime :updated_at, default: Sequel::CURRENT_TIMESTAMP
end
# create many-to-many table between tests and benchmarks
create_table(:benchmarks_tests) do
primary_key :id
foreign_key :benchmark_id, :benchmarks
foreign_key :test_id, :tests
DateTime :created_at, default: Sequel::CURRENT_TIMESTAMP
DateTime :updated_at, default: Sequel::CURRENT_TIMESTAMP
end
# modify results table to integrate with the new tests table
alter_table(:results) do
drop_foreign_key :hardware_id
add_foreign_key :test_id, :tests
end
end
down do
alter_table(:results) do
drop_foreign_key :test_id
add_foreign_key :hardware_id, :hardware
end
drop_table(:benchmarks_tests)
drop_table(:tests)
end
end

50
gulpfile.js Normal file
View File

@@ -0,0 +1,50 @@
const gulp = require('gulp');
const sass = require('gulp-sass')(require('sass'));
const coffee = require('gulp-coffee');
const sourcemaps = require('gulp-sourcemaps');
const plumber = require('gulp-plumber');
// Compile .sass files to compressed CSS
function compileSass() {
return gulp.src('assets/styles/**/*.sass')
.pipe(plumber())
.pipe(sass({ outputStyle: 'compressed' }).on('error', sass.logError))
.pipe(gulp.dest('public/css'));
}
// Compile .coffee files to JavaScript with source maps
function compileCoffee() {
return gulp.src('assets/scripts/**/*.coffee', { sourcemaps: true })
.pipe(plumber())
.pipe(coffee({ bare: true }))
.pipe(gulp.dest('public/js', { sourcemaps: '.' }));
}
// Watch files for changes
function watchFiles(cb) {
gulp.watch('assets/styles/**/*.sass', compileSass);
gulp.watch('assets/scripts/**/*.coffee', compileCoffee);
cb();
}
// Chain all asset builds together
function buildAssets() {
return gulp.parallel(compileSass, compileCoffee);
}
// Perform initial build then watch
function buildAndWatch() {
return gulp.series(
buildAssets(),
watchFiles
);
}
// one-time build
exports.build = buildAssets();
// start builds with file watching
exports.watch = buildAndWatch();
// Define default task (defaults to watch)
exports.default = exports.watch;

3004
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@
"version": "0.1.0",
"main": "src/server.rb",
"scripts": {
"grunt": "grunt"
"gulp": "gulp"
},
"repository": {
"type": "git",
@@ -18,11 +18,11 @@
"author": "Gregory Ballantine <gballantine@bitgoblin.tech>",
"license": "BSD-2-Clause",
"devDependencies": {
"grunt": "^1.6.1",
"grunt-cli": "^1.4.3",
"grunt-contrib-coffee": "^2.1.0",
"grunt-contrib-sass": "^2.0.0",
"grunt-contrib-watch": "^1.1.0",
"sass": "^1.77.4"
"gulp": "^5.0.1",
"gulp-coffee": "^3.0.3",
"gulp-plumber": "^1.2.1",
"gulp-sass": "^6.0.1",
"gulp-sourcemaps": "^3.0.0",
"sass": "^1.89.2"
}
}

View File

@@ -3,6 +3,14 @@
# Helpers - view helper functions
module Helpers
def ruby_version()
return RUBY_VERSION
end
def app_version()
return `git describe --tags`
end
def date_format(date)
dt = date.to_datetime
return dt.strftime('%B %d, %Y @ %I:%M:%S %p %Z')

View File

@@ -3,7 +3,7 @@
# Hardware - database model for PC hardware
class Hardware < Sequel::Model(:hardware)
one_to_many :results
one_to_many :tests
def bench_results
br = {}

View File

@@ -3,3 +3,4 @@
require_relative 'hardware'
require_relative 'benchmark'
require_relative 'result'
require_relative 'test'

View File

@@ -3,7 +3,7 @@
# Result - database model for benchmark results
class Result < Sequel::Model
many_to_one :hardware
many_to_one :test
many_to_one :benchmark
def formatted_score

10
src/models/test.rb Normal file
View File

@@ -0,0 +1,10 @@
# frozen_string_literal: true
# Test - database model for hardware tests
class Test < Sequel::Model
one_to_many :result
many_to_one :hardware
many_to_many :benchmark
end

23
src/routes/api1.rb Normal file
View File

@@ -0,0 +1,23 @@
# frozen_string_literal: true
# /api/v1 routes
class GameData < Sinatra::Base
get '/api/v1/benchmark/details' do
benchmark_id = params[:benchmark_id]
benchmark = Benchmark.where(id: benchmark_id).first()
json benchmark.values()
end
get '/api/v1/results' do
test_id = params[:test_id]
benchmark_id = params[:benchmark_id]
results = Result.where(test_id: test_id, benchmark_id: benchmark_id).all()
json results.map(&:values)
end
end

View File

@@ -4,11 +4,11 @@
class GameData < Sinatra::Base
get '/' do
results = Result.reverse(:updated_at).limit(10).all()
tests = Test.reverse(:updated_at).limit(10).all()
erb :'index/index', locals: {
title: 'Dashboard',
results: results
tests: tests
}
end

View File

@@ -3,5 +3,8 @@
require_relative 'index'
require_relative 'hardware'
require_relative 'benchmark'
require_relative 'result'
require_relative 'reports'
require_relative 'result'
require_relative 'test'
require_relative 'api1'

View File

@@ -3,18 +3,18 @@
# /reports routes
class GameData < Sinatra::Base
get '/reports' do
get '/report' do
benchmarks = Benchmark.order(:name).all()
hardware = Hardware.order(:name).all()
tests = Test.order(:name).all()
erb :'reports/index', locals: {
title: 'Generate Reports',
hardware: hardware,
tests: tests,
benchmarks: benchmarks
}
end
post '/reports' do
post '/report' do
report_type = params[:type]
report_choice = params[:choice]
report_compare = params[:compare]
@@ -26,10 +26,10 @@ class GameData < Sinatra::Base
min_results = []
report_compare.each do |c|
hrd = Hardware.where(id: c).first()
names.push(hrd.name)
tst = Test.where(id: c).first()
names.push(tst.name)
res = Result.where(benchmark_id: report_choice, hardware_id: c).first()
res = Result.where(benchmark_id: report_choice, test_id: c).first()
avg_results.push(res.avg_score)
min_results.push(res.min_score)
end

View File

@@ -3,31 +3,12 @@
# /result routes
class GameData < Sinatra::Base
get '/result' do
results = Result.reverse(:updated_at).limit(10).all()
erb :'result/index', locals: {
title: 'List of Results',
results: results
}
end
get '/result/add' do
hardware = Hardware.all()
benchmarks = Benchmark.all()
erb :'result/add', locals: {
title: 'Add Result',
hardware: hardware,
benchmarks: benchmarks
}
end
post '/result/add' do
result_minimum = params[:result_minimum] if params.key?(:result_minimum)
result_maximum = params[:result_maximum] if params.key?(:result_maximum)
Result.create(
hardware_id: params[:result_hardware],
test_id: params[:result_test],
benchmark_id: params[:result_benchmark],
avg_score: params[:result_average],
min_score: result_minimum,
@@ -35,8 +16,8 @@ class GameData < Sinatra::Base
)
if params.key?(:result_referrer)
if params[:result_referrer] == 'hardware'
redirect "/hardware/#{params[:result_hardware]}"
if params[:result_referrer] == 'test'
redirect "/test/#{params[:result_test]}"
elsif params[:result_referrer] == 'benchmark'
redirect "/benchmark/#{params[:result_benchmark]}"
end

68
src/routes/test.rb Normal file
View File

@@ -0,0 +1,68 @@
# frozen_string_literal: true
# /test routes
class GameData < Sinatra::Base
get '/test' do
tests = Test.reverse(:updated_at).limit(10).all()
erb :'test/index', locals: {
title: 'List of Tests',
tests: tests
}
end
get '/test/add' do
hardware = Hardware.order(:name).all()
benchmarks = Benchmark.order(:name).all()
erb :'test/add', locals: {
title: 'Add Test',
hardware: hardware,
benchmarks: benchmarks
}
end
post '/test/add' do
tst = Test.create(
name: params[:test_name],
hardware_id: params[:test_hardware],
description: params[:test_description]
)
# create an array of the selected benchmarks
benchmarks = Array(params[:test_benchmarks])
# associate the benchmarks to the test
benchmarks.each do |b|
tst.add_benchmark(b)
end
redirect "/test/#{tst.id}"
end
get '/test/:test_id' do
tst = Test.where(id: params[:test_id]).first()
erb :'test/view', locals: {
title: tst.name,
test: tst
}
end
get '/test/:hardware_id/edit' do
hardware = Hardware.where(id: params[:hardware_id]).first()
erb :'test/edit', locals: {
title: "Editing: #{hardware.name}",
hardware: hardware
}
end
post '/test/:hardware_id/edit' do
hardware = Hardware.where(id: params[:hardware_id]).first()
hardware.update(
name: params[:hardware_name],
type: params[:hardware_type]
)
redirect "/hardware/#{hardware.id}"
end
end

View File

@@ -1,43 +1,36 @@
<div class="grid-x grid-margin-x">
<div class="cell small-12">
<div class="row mb-4">
<div class="col-12">
<h1>Add new benchmark</h1>
</div>
</div>
<div class="grid-x grid-margin-x">
<div class="row">
<form class="cell small-12" action="/benchmark/add" method="post">
<div class="grid-x grid-padding-x">
<div class="cell medium-9">
<label>
Benchmark name
<input type="text" name="benchmark_name" placeholder="Example benchmark">
</label>
<form class="col-12" action="/benchmark/add" method="post">
<div class="row mb-3">
<div class="col-9">
<label for="benchmark_name">Benchmark name</label>
<input id="benchmark_name" class="form-control" type="text" name="benchmark_name" placeholder="Example benchmark">
</div>
<div class="cell medium-3">
<label>
Scoring type
<select name="benchmark_scoring">
<option value="fps">Frames per Second (fps)</option>
<option value="ms">Frame Time (ms)</option>
<option value="pts">Total Points</option>
</select>
</label>
<div class="col-3">
<label for="benchmark_scoring">Scoring type</label>
<select id="benchmark_scoring" class="form-select" name="benchmark_scoring">
<option value="fps">Frames per Second (fps)</option>
<option value="ms">Frame Time (ms)</option>
<option value="pts">Total Points</option>
</select>
</div>
</div>
<div class="grid-x grid-padding-x">
<div class="cell small-12">
<textarea name="benchmark_description" class="cell small-12">Enter a description/notes here.</textarea>
<div class="row mb-3">
<div class="col-12">
<label for="benchmark_description">Benchmark description</label>
<textarea id="benchmark_description" class="form-control" name="benchmark_description">Enter a description/notes here.</textarea>
</div>
</div>
<div class="grid-x grid-padding-x">
<div class="cell small-12">
<input type="submit" class="button" value="Submit">
</div>
</div>
<input class="btn btn-primary" type="submit" value="Create Benchmark">
</form>
</div>

View File

@@ -1,43 +1,36 @@
<div class="grid-x grid-margin-x">
<div class="cell small-12">
<div class="row mb-4">
<div class="col-12">
<h1>Editing: <%= benchmark.name %></h1>
</div>
</div>
<div class="grid-x grid-margin-x">
<div class="row">
<form class="cell small-12" action="/benchmark/<%= benchmark.id %>/edit" method="post">
<div class="grid-x grid-padding-x">
<div class="cell medium-9">
<label>
Benchmark name
<input type="text" name="benchmark_name" placeholder="Example benchmark" value="<%= benchmark.name %>">
</label>
<div class="row mb-3">
<div class="col-9">
<label for="benchmark_name">Benchmark name</label>
<input id="benchmark_name" class="form-control" type="text" name="benchmark_name" placeholder="Example benchmark" value="<%= benchmark.name %>">
</div>
<div class="cell medium-3">
<label>
Scoring type
<select name="benchmark_scoring">
<option value="fps" <% if benchmark.scoring == 'fps' %>selected<% end %>>Frames per Second (fps)</option>
<option value="ms" <% if benchmark.scoring == 'ms' %>selected<% end %>>Frame Time (ms)</option>
<option value="pts" <% if benchmark.scoring == 'pts' %>selected<% end %>>Total Points</option>
</select>
</label>
<div class="col-3">
<label for="benchmark_scoring">Scoring type</label>
<select id="benchmark_scoring" class="form-select" name="benchmark_scoring">
<option value="fps" <% if benchmark.scoring == 'fps' %>selected<% end %>>Frames per Second (fps)</option>
<option value="ms" <% if benchmark.scoring == 'ms' %>selected<% end %>>Frame Time (ms)</option>
<option value="pts" <% if benchmark.scoring == 'pts' %>selected<% end %>>Total Points</option>
</select>
</div>
</div>
<div class="grid-x grid-padding-x">
<div class="cell small-12">
<textarea name="benchmark_description" class="cell small-12"><%= benchmark.description %></textarea>
<div class="row mb-3">
<div class="col-12">
<label for="benchmark_description">Benchmark description</label>
<textarea id="benchmark_description" class="form-control" name="benchmark_description"><%= benchmark.description %></textarea>
</div>
</div>
<div class="grid-x grid-padding-x">
<div class="cell small-12">
<input type="submit" class="button" value="Submit">
</div>
</div>
<input class="btn btn-primary" type="submit" value="Submit Changes">
</form>
</div>

View File

@@ -1,20 +1,20 @@
<div class="grid-x grid-margin-x">
<div class="cell small-12">
<div class="row mb-3">
<div class="col-12">
<h1>List of benchmarks</h1>
</div>
<div class="cell small-12">
<div class="col-12">
<p>
<a href="/benchmark/add">Add new benchmark</a>
</p>
</div>
</div>
<div class="grid-x grid-margin-x">
<div class="row">
<% if benchmarks.length > 0 %>
<div class="cell small-12">
<table>
<thead>
<div class="col-12">
<table class="table table-hover table-responsive">
<thead class="table-light">
<tr>
<th>Benchmark name</th>
<th>Scoring type</th>
@@ -24,7 +24,7 @@
<tbody>
<% benchmarks.each do |b| %>
<tr>
<td><a href="/benchmark/<%= b.id %>"><%= b.name %></a</td>
<td><a href="/benchmark/<%= b.id %>"><%= b.name %></a></td>
<td><%= b.scoring %></td>
<td><%= b.description %></td>
</tr>
@@ -33,7 +33,7 @@
</table>
</div>
<% else %>
<div class="cell small-12">
<div class="col-12">
<p>I'm sorry, there doesn't appear to be any benchmarks added yet. Check again later!</p>
</div>
<% end %>

View File

@@ -1,17 +1,17 @@
<div class="grid-x grid-margin-x">
<div class="cell small-12">
<div class="row">
<div class="col-12">
<h1><%= benchmark.name %></h1>
</div>
<div class="cell small-12">
<div class="col-12">
<p><a href="/benchmark/<%= benchmark.id %>/edit">Edit</a></p>
</div>
<div class="cell small-12">
<div class="col-12">
Benchmark scoring type: <%= benchmark.scoring %>
</div>
<div class="cell small-12">
<div class="col-12">
Description:
<p><%= benchmark.description %></p>
</div>

View File

@@ -1,32 +1,28 @@
<div class="grid-x grid-margin-x">
<div class="cell small-12">
<div class="row mb-3">
<div class="col-12">
<h1>Add new hardware</h1>
</div>
</div>
<div class="grid-x grid-margin-x">
<div class="row mb-3">
<form class="cell small-12" action="/hardware/add" method="post">
<div class="grid-x grid-padding-x">
<div class="cell medium-9">
<label>
Hardware name
<input type="text" name="hardware_name" placeholder="Example hardware">
</label>
<form class="col-12" action="/hardware/add" method="post">
<div class="row mb-3">
<div class="col-12 col-md-9">
<label for="hardware_name">Hardware name</label>
<input id="hardware_name" class="form-control" type="text" name="hardware_name" placeholder="Example hardware">
</div>
<div class="cell medium-3">
<label>
Type
<select name="hardware_type">
<option value="gpu">Graphics card</option>
<option value="cpu">Processor</option>
</select>
</label>
<div class="col-12 col-md-3">
<label for="hardware_type">Type</label>
<select id="hardware_type" class="form-select" name="hardware_type">
<option value="gpu">Graphics card</option>
<option value="cpu">Processor</option>
</select>
</div>
</div>
<input type="submit" class="button" value="Submit">
<input class="btn btn-primary" type="submit" value="Create Hardware">
</form>
</div>

View File

@@ -1,32 +1,28 @@
<div class="grid-x grid-margin-x">
<div class="cell small-12">
<h1>Editing: <%= hardware.name %></h1>
<div class="row mb-3">
<div class="col-12">
<h1>Add new hardware</h1>
</div>
</div>
<div class="grid-x grid-margin-x">
<div class="row mb-3">
<form class="cell small-12" action="/hardware/<%= hardware.id %>/edit" method="post">
<div class="grid-x grid-padding-x">
<div class="cell medium-9">
<label>
Hardware name
<input type="text" name="hardware_name" placeholder="Example hardware" value="<%= hardware.name %>">
</label>
<form class="col-12" action="/hardware/<%= hardware.id %>/edit" method="post">
<div class="row mb-3">
<div class="col-12 col-md-9">
<label for="hardware_name">Hardware name</label>
<input id="hardware_name" class="form-control" type="text" name="hardware_name" placeholder="Example hardware" value="<%= hardware.name %>">
</div>
<div class="cell medium-3">
<label>
Type
<select name="hardware_type">
<option value="gpu" <% if hardware.type == 'gpu' %>selected<% end %>>Graphics card</option>
<div class="col-12 col-md-3">
<label for="hardware_type">Type</label>
<select id="hardware_type" class="form-select" name="hardware_type">
<option value="gpu" <% if hardware.type == 'gpu' %>selected<% end %>>Graphics card</option>
<option value="cpu" <% if hardware.type == 'cpu' %>selected<% end %>>Processor</option>
</select>
</label>
</select>
</div>
</div>
<input type="submit" class="button" value="Submit">
<input class="btn btn-primary" type="submit" value="Create Hardware">
</form>
</div>

View File

@@ -1,20 +1,20 @@
<div class="grid-x grid-margin-x">
<div class="cell small-12">
<div class="row mb-3">
<div class="col-12">
<h1>List of hardware</h1>
</div>
<div class="cell small-12">
<div class="col-12">
<p>
<a href="/hardware/add">Add new hardware</a>
</p>
</div>
</div>
<div class="grid-x grid-margin-x">
<div class="row mb-3">
<% if hardware.length > 0 %>
<div class="cell small-12">
<table>
<thead>
<div class="col-12">
<table class="table table-hover table-responsive">
<thead class="table-light">
<tr>
<th>Hardware name</th>
<th>Type</th>
@@ -35,7 +35,7 @@
</table>
</div>
<% else %>
<div class="cell small-12">
<div class="col-12">
<p>I'm sorry, there doesn't appear to be any hardware added yet. Check again later!</p>
</div>
<% end %>

View File

@@ -1,89 +1,13 @@
<div class="grid-x grid-margin-x">
<div class="cell small-12">
<div class="row">
<div class="col-12">
<h1><%= hardware.name %></h1>
</div>
<div class="cell small-12">
<div class="col-12">
<p><a href="/hardware/<%= hardware.id %>/edit">Edit</a></p>
</div>
<div class="cell small-12">
<div class="col-12">
Hardware type: <%= hardware.type %>
</div>
</div>
<hr>
<div class="grix-x grix-margin-x">
<div class="cell small-12">
<form class="u-full-width" action="/result/add" method="post">
<input type="hidden" name="result_hardware" value="<%= hardware.id %>">
<input type="hidden" name="result_referrer" value="hardware">
<div class="grid-x grid-margin-x">
<div class="cell medium-5">
<label for="result_benchmark">
Add benchmark result:
<select class="u-full-width" id="result_benchmark" name="result_benchmark">
<% benchmarks.each do |b| %>
<option value="<%= b.id %>"><%= b.name %></option>
<% end %>
</select>
</label>
</div>
<div class="cell medium-2">
<label for="result_average">
Average score:
<input type="text" id="result_average" name="result_average" value="">
</label>
</div>
<div class="cell medium-2">
<label for="result_minimum">
Minimum score:
<input type="text" id="result_minimum" name="result_minimum" value="">
</label>
</div>
<div class="cell medium-2">
<label for="result_maximum">
Maximum score:
<input type="text" id="result_maximum" name="result_maximum" value="">
</label>
</div>
<div class="cell medium-1">
<input type="submit" class="u-full-width button" value="Submit">
</div>
</div>
</form>
<hr>
<h4>Benchmark results involving this hardware:</h4>
<table>
<thead>
<th>Benchmark name</th>
<th>Scoring type</th>
<th># results</th>
<th>Average</th>
<th>Minimum</th>
<th>Maximum</th>
</thead>
<tbody>
<% hardware.bench_results().each do |k, r| %>
<tr>
<td><%= k %></td>
<td>N/a</td>
<td><%= r.length %></td>
<td><%= average_array(r) %></td>
<td>N/a</td>
<td>N/a</td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>

View File

@@ -1,30 +1,31 @@
<div class="grid-x grid-margin-x">
<% if results.length > 0 %>
<div class="cell small-12">
<div class="row">
<% if tests.length > 0 %>
<div class="twelve columns">
<h2>Latest benchmark results:</h2>
</div>
<div class="cell small-12">
<div class="twelve columns">
<table>
<thead>
<tr>
<th>Hardware tested</th>
<th>Benchmark used</th>
<th>Score</th>
<th>Test name</th>
<th># Benchmarks</th>
<th>Last Updated</th>
</tr>
</thead>
<tbody>
<% results.each do |r| %>
<% tests.each do |t| %>
<tr>
<td><%= r.hardware.name %></td>
<td><%= r.benchmark.name %></td>
<td><%= r.formatted_score() %></td>
<td><a href="/test/<%= t.id %>"><%= t.name %></a></td>
<td><%= t.benchmark.length %></td>
<td><%= t.updated_at %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
<% else %>
<div class="cell small-12">
<div class="twelve columns">
<p>I'm sorry, there don't appear to be any benchmark results logged yet. Check again later!</p>
</div>
<% end %>

View File

@@ -5,10 +5,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title><%= title %> | Game Data</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.7.5/css/foundation.min.css">
<link rel="stylesheet" href="/css/remmington.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.7.5/js/foundation.min.js" charset="utf-8"></script>
<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">
<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="/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>
@@ -17,8 +17,11 @@
<%= erb :'partials/navbar', :locals => locals %>
<!-- main content -->
<div class="grid-container">
<div id="wrapper" class="container mb-4">
<%= yield %>
</div>
<!-- site footer -->
<%= erb :'partials/footer', :locals => locals %>
</body>
</html>

View File

@@ -0,0 +1,8 @@
<nav id="main-footer" class="container">
<div class="row">
<div class="col-12">
<p>Game Data version v<%= app_version() %></p>
<p>Running Ruby version v<%= ruby_version() %></p>
</div>
</div>
</nav>

View File

@@ -1,11 +1,29 @@
<div id="main-nav" class="top-bar">
<div class="top-bar-left">
<ul class="menu">
<li><a href="/">Dashboard</a></li>
<li><a href="/hardware">Hardware</a></li>
<li><a href="/benchmark">Benchmarks</a></li>
<li><a href="/result">Results</a></li>
<li><a href="/reports">Reports</a></li>
</ul>
<div id="main-nav" class="navbar navbar-expand-md bg-body-secondary mb-3">
<div class="container-fluid">
<a class="navbar-brand mb-0 h1" href="#">Game Data</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>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-md-0">
<li class="nav-item">
<a class="nav-link" href="/">Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/benchmark">Benchmarks</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/hardware">Hardware</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/test">Test</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/report">Reports</a>
</li>
</ul>
</div>
</div>
</div>

View File

@@ -1,12 +1,12 @@
<div class="grid-x grid-margin-x">
<form class="cell small-12" action="/reports" method="post">
<div class="row">
<form class="col-12" action="/reports" method="post">
<div class="grid-x grid-margin-x">
<select class="cell medium-6" id="report_type" name="report_type" disabled>
<select class="col-12 col-md-6 form-select" id="report_type" name="report_type" disabled>
<option value="benchmark">Benchmark</option>
<option value="hardware">Hardware</option>
<option value="test">Test</option>
</select>
<select class="cell medium-6" id="report_choice" name="report_choice">
<select class="col-12 col-md-6 form-select" id="report_choice" name="report_choice">
<% benchmarks.each do |b| %>
<option value="<%= b.id %>"><%= b.name %></option>
<% end %>
@@ -14,14 +14,14 @@
</div>
<div class="grid-x grid-margin-x">
<select class="cell small-12" id="report_compare" name="report_compare[]" multiple>
<% hardware.each do |h| %>
<option value="<%= h.id %>"><%= h.name %></option>
<select class="col-12 form-select" id="report_compare" name="report_compare[]" multiple>
<% tests.each do |t| %>
<option value="<%= t.id %>"><%= t.name %></option>
<% end %>
</select>
</div>
<input type="submit" class="button" id="generate_button" value="Generate">
<input type="submit" class="btn btn-primary" id="generate_button" value="Generate">
<a href="#" class="button" id="download_button" disabled>Download</a>
<div class="grid-x grid-margin-x">

View File

@@ -1,60 +0,0 @@
<div class="grid-x grid-margin-x">
<div class="cell small-12">
<h1>Add new result</h1>
</div>
</div>
<div class="grid-x grid-margin-x">
<form class="cell small-12" action="/result/add" method="post">
<div class="grid-x grid-padding-x">
<div class="cell medium-6">
<label>
Hardware:
<select name="result_hardware">
<% hardware.each do |h| %>
<option value="<%= h.id %>"><%= h.name %></option>
<% end %>
</select>
</label>
</div>
<div class="cell medium-6">
<label>
Benchmark:
<select name="result_benchmark">
<% benchmarks.each do |b| %>
<option value="<%= b.id %>"><%= b.name %></option>
<% end %>
</select>
</label>
</div>
</div>
<div class="grid-x grid-padding-x">
<div class="cell medium-4">
<label>
Average score:
<input type="number" name="result_average" value="0.0" step="0.01" required>
</label>
</div>
<div class="cell medium-4">
<label>
Minimum score:
<input type="number" name="result_minimum" value="0.0" step="0.01">
</label>
</div>
<div class="cell medium-4">
<label>
Maximum score:
<input type="number" name="result_maximum" value="0.0" step="0.01">
</label>
</div>
</div>
<input type="submit" class="button" value="Submit">
</form>
</div>

View File

@@ -1,44 +0,0 @@
<div class="grid-x grid-margin-x">
<div class="cell small-12">
<h1>List of results</h1>
</div>
<div class="cell small-12">
<p>
<a href="/result/add">Add new result</a>
</p>
</div>
</div>
<div class="grid-x grid-margin-x">
<% if results.length > 0 %>
<div class="cell small-12">
<table>
<thead>
<tr>
<th>Hardware</th>
<th>Benchmark</th>
<th>Score (type)</th>
<th>Date added</th>
<th>Date modified</th>
</tr>
</thead>
<tbody>
<% results.each do |r| %>
<tr>
<td><%= r.hardware.name %></td>
<td><%= r.benchmark.name %></td>
<td><%= r.score %> (<%= r.benchmark.scoring %>)</td>
<td><%= date_format(r.created_at) %></td>
<td><%= date_format(r.updated_at) %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
<% else %>
<div class="cell small-12">
<p>I'm sorry, there don't appear to be any results added yet. Check again later!</p>
</div>
<% end %>
</div>

46
views/test/add.erb Normal file
View File

@@ -0,0 +1,46 @@
<div class="row mb-3">
<div class="col-12">
<h1>Add new test</h1>
</div>
</div>
<div class="row">
<form class="col-12" action="/test/add" method="post">
<div class="row mb-3">
<div class="col-12 col-md-6 mb-3">
<label for="test_name">Test name</label>
<input id="test_name" class="form-control" type="text" name="test_name" placeholder="My hardware test (01/99)">
</div>
<div class="col-12 col-md-6 mb-3">
<label for="test_hardware">Hardware to test</label>
<select id="test_hardware" class="form-select" name="test_hardware">
<% for h in hardware %>
<option value="<%= h.id %>"><%= h.name %></option>
<% end %>
</select>
</div>
<div class="col-12 col-md-4 mb-3">
<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">
<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..."></textarea>
</div>
<div class="row">
<div class="col-12">
<input class="btn btn-primary" type="submit" value="Create Test">
</div>
</div>
</form>
</div>

32
views/test/edit.erb Normal file
View File

@@ -0,0 +1,32 @@
<div class="grid-x grid-margin-x">
<div class="cell small-12">
<h1>Editing: <%= hardware.name %></h1>
</div>
</div>
<div class="grid-x grid-margin-x">
<form class="cell small-12" action="/hardware/<%= hardware.id %>/edit" method="post">
<div class="grid-x grid-padding-x">
<div class="cell medium-9">
<label>
Hardware name
<input type="text" name="hardware_name" placeholder="Example hardware" value="<%= hardware.name %>">
</label>
</div>
<div class="cell medium-3">
<label>
Type
<select name="hardware_type">
<option value="gpu" <% if hardware.type == 'gpu' %>selected<% end %>>Graphics card</option>
<option value="cpu" <% if hardware.type == 'cpu' %>selected<% end %>>Processor</option>
</select>
</label>
</div>
</div>
<input type="submit" class="button" value="Submit">
</form>
</div>

42
views/test/index.erb Normal file
View File

@@ -0,0 +1,42 @@
<div class="row mb-3">
<div class="col-12">
<h1>List of tests</h1>
</div>
<div class="col-12">
<p>
<a href="/test/add">Add new test</a>
</p>
</div>
</div>
<div class="row mb-3">
<% if tests.length > 0 %>
<div class="col-12">
<table class="table table-hover table-responsive">
<thead class="table-light">
<tr>
<th>Test name</th>
<th># of benchmarks</th>
<th>Date added</th>
<th>Date modified</th>
</tr>
</thead>
<tbody>
<% tests.each do |t| %>
<tr>
<td><a href="/test/<%= t.id %>"><%= t.name %></a></td>
<td><%= t.benchmark.length %></td>
<td><%= date_format(t.created_at) %></td>
<td><%= date_format(t.updated_at) %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
<% else %>
<div class="col-12">
<p>I'm sorry, there doesn't appear to be any tests added yet. Check again later!</p>
</div>
<% end %>
</div>

91
views/test/view.erb Normal file
View File

@@ -0,0 +1,91 @@
<div class="grid-x grid-margin-x">
<div class="cell small-12">
<h1><%= test.name %></h1>
</div>
<div class="cell small-12">
<p><a href="/test/<%= test.id %>/edit">Edit</a></p>
</div>
<div class="cell small-12">
Hardware tested: <%= test.hardware.name %>
</div>
<div class="cell small-12">
<p><%= test.description %></p>
</div>
</div>
<hr>
<div class="grix-x grix-margin-x">
<div class="cell small-12">
<form class="u-full-width" action="/result/add" method="post">
<input type="hidden" name="result_test" value="<%= test.id %>">
<input type="hidden" name="result_referrer" value="test">
<div class="grid-x grid-margin-x">
<div class="cell medium-5">
<label for="result_benchmark">
Add benchmark result:
<select class="u-full-width" id="result_benchmark" name="result_benchmark">
<% test.benchmark.each do |b| %>
<option value="<%= b.id %>"><%= b.name %></option>
<% end %>
</select>
</label>
</div>
<div class="cell medium-2">
<label for="result_average">
Average score:
<input type="text" id="result_average" name="result_average" value="">
</label>
</div>
<div class="cell medium-2">
<label for="result_minimum">
Minimum score:
<input type="text" id="result_minimum" name="result_minimum" value="">
</label>
</div>
<div class="cell medium-2">
<label for="result_maximum">
Maximum score:
<input type="text" id="result_maximum" name="result_maximum" value="">
</label>
</div>
<div class="cell medium-1">
<input type="submit" class="u-full-width button" value="Submit">
</div>
</div>
</form>
<hr>
<h4>Benchmark results for this test:</h4>
<table id="results-table" data-test-id="<%= test.id %>">
<thead>
<tr>
<th>Benchmark name</th>
<th>Scoring type</th>
<th># results</th>
<th>Average</th>
<th>Minimum</th>
<th>Maximum</th>
</tr>
</thead>
<tbody>
<% test.benchmark.each do |benchmark| %>
<tr data-benchmark-id="<%= benchmark.id %>"></tr>
<% end %>
</tbody>
</table>
</div>
</div>
<!-- load test data fetching functionality -->
<script src="/js/test.js" charset="utf-8"></script>