Compare commits
56 Commits
28b6cc66bb
...
v0.2.1
Author | SHA1 | Date | |
---|---|---|---|
39f95575da | |||
6e1ab89209 | |||
9cd6c78741 | |||
5b730df803 | |||
0ce4a3ecee | |||
12ece12394 | |||
05c20b5811 | |||
bd822664b0 | |||
3f0efce0d8 | |||
eeedc57cd3 | |||
164eea1bde | |||
85fe3b0b38 | |||
519955e57a | |||
96b746822c | |||
eac833fd6d | |||
ad391c84a4 | |||
641c9315bc | |||
3a136865b0 | |||
|
f40d69a98d | ||
|
40cfdcc2a3 | ||
|
260d0d1268 | ||
|
e1f5bd3950 | ||
|
1f0c481105 | ||
|
dd8e419e52 | ||
|
c74ca114d8 | ||
0a1037e79a | |||
|
bc5ae4962f | ||
|
ec2bf45a6e | ||
57163b10e4 | |||
25d394627d | |||
85dfdb163a | |||
b593ef7593 | |||
26698082f4 | |||
42a0b95015 | |||
5cc3b8f824 | |||
d59c75281e | |||
55e4f397f8 | |||
49d1276031 | |||
bc70fb8dd0 | |||
0231ebad2d | |||
541b5236f0 | |||
|
6215cecb53 | ||
|
886f566ae2 | ||
|
fdd350e16f | ||
bc4cb181c3 | |||
822f49bcc2 | |||
aec77628f7 | |||
ecb696372d | |||
31b8404be1 | |||
8cd47d7e70 | |||
d17b66920a | |||
47cb580393 | |||
883019b181 | |||
2cc80e239b | |||
ed085e4b40 | |||
cf9235cb18 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -65,3 +65,6 @@ node_modules/
|
|||||||
# Compiled assets
|
# Compiled assets
|
||||||
public/css/
|
public/css/
|
||||||
public/js/
|
public/js/
|
||||||
|
|
||||||
|
# Ignore production configuration files to protect against credential leaks
|
||||||
|
config/production.yaml
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
require: rubocop-sequel
|
plugins:
|
||||||
|
- rubocop-rspec
|
||||||
|
- rubocop-sequel
|
||||||
|
|
||||||
AllCops:
|
AllCops:
|
||||||
NewCops: enable
|
NewCops: enable
|
||||||
|
@@ -1,11 +1,32 @@
|
|||||||
pipeline:
|
steps:
|
||||||
style:
|
setup:
|
||||||
image: ruby:3.0
|
image: ruby:3.4
|
||||||
|
env:
|
||||||
|
RACK_ENV: testing
|
||||||
commands:
|
commands:
|
||||||
- 'gem install rake'
|
- gem install rake
|
||||||
- 'bundle config set --local path "vendor/bundle"'
|
- bundle config set --local path "vendor/bundle"
|
||||||
- 'bundle install'
|
- bundle install
|
||||||
- 'rake test:rubocop'
|
- rake db:migrate
|
||||||
|
|
||||||
|
test_ruby34:
|
||||||
|
image: ruby:3.4
|
||||||
|
env:
|
||||||
|
RACK_ENV: testing
|
||||||
|
commands:
|
||||||
|
- gem install rake
|
||||||
|
- bundle config set --local path "vendor/bundle"
|
||||||
|
- rake test:unit
|
||||||
|
group: tests
|
||||||
|
|
||||||
|
style:
|
||||||
|
image: ruby:3.4
|
||||||
|
env:
|
||||||
|
RACK_ENV: testing
|
||||||
|
commands:
|
||||||
|
- gem install rake
|
||||||
|
- bundle config set --local path "vendor/bundle"
|
||||||
|
- rake test:lint
|
||||||
|
|
||||||
gitea_release:
|
gitea_release:
|
||||||
image: plugins/gitea-release
|
image: plugins/gitea-release
|
||||||
@@ -15,5 +36,5 @@ pipeline:
|
|||||||
base_url: https://git.metaunix.net
|
base_url: https://git.metaunix.net
|
||||||
title: "${CI_COMMIT_TAG}"
|
title: "${CI_COMMIT_TAG}"
|
||||||
when:
|
when:
|
||||||
event: tag
|
event:
|
||||||
|
- tag
|
||||||
|
@@ -2,7 +2,7 @@ FROM ruby:3.4
|
|||||||
|
|
||||||
RUN gem install bundler
|
RUN gem install bundler
|
||||||
|
|
||||||
WORKDIR /src
|
WORKDIR /usr/src/game-data
|
||||||
|
|
||||||
COPY Gemfile Gemfile.l*ck ./
|
COPY Gemfile Gemfile.l*ck ./
|
||||||
|
|
||||||
@@ -13,3 +13,4 @@ RUN gem install rake
|
|||||||
COPY . ./
|
COPY . ./
|
||||||
|
|
||||||
ENTRYPOINT ["bash", "entrypoints/dev.sh"]
|
ENTRYPOINT ["bash", "entrypoints/dev.sh"]
|
||||||
|
|
||||||
|
13
Dockerfile.gulp
Normal file
13
Dockerfile.gulp
Normal 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" ]
|
12
Gemfile
12
Gemfile
@@ -1,14 +1,13 @@
|
|||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
gem 'sinatra', '~> 3.2'
|
gem 'sinatra', '~> 4.1'
|
||||||
gem 'sinatra-contrib', '~> 3.2'
|
gem 'sinatra-contrib', '~> 4.1'
|
||||||
gem 'puma', '~> 6.6'
|
gem 'puma', '~> 6.6'
|
||||||
|
|
||||||
gem 'sequel', '~> 5.92'
|
gem 'sequel', '~> 5.92'
|
||||||
gem 'sqlite3', '~> 2.6'
|
gem 'sqlite3', '~> 2.6'
|
||||||
|
|
||||||
gem 'logger'
|
gem 'logger'
|
||||||
gem 'ostruct'
|
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
gem 'rerun'
|
gem 'rerun'
|
||||||
@@ -16,5 +15,12 @@ group :development, :test do
|
|||||||
|
|
||||||
# rubocop and extensions for code style
|
# rubocop and extensions for code style
|
||||||
gem 'rubocop'
|
gem 'rubocop'
|
||||||
|
gem 'rubocop-rspec'
|
||||||
gem 'rubocop-sequel'
|
gem 'rubocop-sequel'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
group :test do
|
||||||
|
gem 'rspec'
|
||||||
|
gem 'rack-test'
|
||||||
|
gem 'database_cleaner-sequel'
|
||||||
|
end
|
||||||
|
100
Gemfile.lock
100
Gemfile.lock
@@ -2,21 +2,34 @@ GEM
|
|||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
ast (2.4.3)
|
ast (2.4.3)
|
||||||
base64 (0.2.0)
|
base64 (0.3.0)
|
||||||
bigdecimal (3.2.0)
|
bigdecimal (3.2.2)
|
||||||
|
database_cleaner-core (2.0.1)
|
||||||
|
database_cleaner-sequel (2.0.2)
|
||||||
|
database_cleaner-core (~> 2.0.0)
|
||||||
|
sequel
|
||||||
|
diff-lcs (1.6.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-gnu)
|
||||||
|
ffi (1.17.2-x86_64-linux-musl)
|
||||||
json (2.12.2)
|
json (2.12.2)
|
||||||
language_server-protocol (3.17.0.5)
|
language_server-protocol (3.17.0.5)
|
||||||
lint_roller (1.1.0)
|
lint_roller (1.1.0)
|
||||||
listen (3.9.0)
|
listen (3.9.0)
|
||||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||||
rb-inotify (~> 0.9, >= 0.9.10)
|
rb-inotify (~> 0.9, >= 0.9.10)
|
||||||
logger (1.6.4)
|
logger (1.7.0)
|
||||||
multi_json (1.15.0)
|
multi_json (1.15.0)
|
||||||
mustermann (3.0.3)
|
mustermann (3.0.3)
|
||||||
ruby2_keywords (~> 0.0.1)
|
ruby2_keywords (~> 0.0.1)
|
||||||
nio4r (2.7.4)
|
nio4r (2.7.4)
|
||||||
ostruct (0.6.1)
|
|
||||||
parallel (1.27.0)
|
parallel (1.27.0)
|
||||||
parser (3.3.8.0)
|
parser (3.3.8.0)
|
||||||
ast (~> 2.4.1)
|
ast (~> 2.4.1)
|
||||||
@@ -25,10 +38,16 @@ GEM
|
|||||||
puma (6.6.0)
|
puma (6.6.0)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
racc (1.8.1)
|
racc (1.8.1)
|
||||||
rack (2.2.16)
|
rack (3.2.0)
|
||||||
rack-protection (3.2.0)
|
rack-protection (4.1.1)
|
||||||
base64 (>= 0.1.0)
|
base64 (>= 0.1.0)
|
||||||
rack (~> 2.2, >= 2.2.4)
|
logger (>= 1.6.0)
|
||||||
|
rack (>= 3.0.0, < 4)
|
||||||
|
rack-session (2.1.1)
|
||||||
|
base64 (>= 0.1.0)
|
||||||
|
rack (>= 3.0.0)
|
||||||
|
rack-test (2.2.0)
|
||||||
|
rack (>= 1.3)
|
||||||
rainbow (3.1.1)
|
rainbow (3.1.1)
|
||||||
rb-fsevent (0.11.2)
|
rb-fsevent (0.11.2)
|
||||||
rb-inotify (0.11.1)
|
rb-inotify (0.11.1)
|
||||||
@@ -36,7 +55,20 @@ GEM
|
|||||||
regexp_parser (2.10.0)
|
regexp_parser (2.10.0)
|
||||||
rerun (0.14.0)
|
rerun (0.14.0)
|
||||||
listen (~> 3.0)
|
listen (~> 3.0)
|
||||||
rubocop (1.75.8)
|
rspec (3.13.1)
|
||||||
|
rspec-core (~> 3.13.0)
|
||||||
|
rspec-expectations (~> 3.13.0)
|
||||||
|
rspec-mocks (~> 3.13.0)
|
||||||
|
rspec-core (3.13.5)
|
||||||
|
rspec-support (~> 3.13.0)
|
||||||
|
rspec-expectations (3.13.5)
|
||||||
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
|
rspec-support (~> 3.13.0)
|
||||||
|
rspec-mocks (3.13.5)
|
||||||
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
|
rspec-support (~> 3.13.0)
|
||||||
|
rspec-support (3.13.4)
|
||||||
|
rubocop (1.76.1)
|
||||||
json (~> 2.3)
|
json (~> 2.3)
|
||||||
language_server-protocol (~> 3.17.0.2)
|
language_server-protocol (~> 3.17.0.2)
|
||||||
lint_roller (~> 1.1.0)
|
lint_roller (~> 1.1.0)
|
||||||
@@ -44,49 +76,75 @@ GEM
|
|||||||
parser (>= 3.3.0.2)
|
parser (>= 3.3.0.2)
|
||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
regexp_parser (>= 2.9.3, < 3.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)
|
ruby-progressbar (~> 1.7)
|
||||||
unicode-display_width (>= 2.4.0, < 4.0)
|
unicode-display_width (>= 2.4.0, < 4.0)
|
||||||
rubocop-ast (1.44.1)
|
rubocop-ast (1.45.1)
|
||||||
parser (>= 3.3.7.2)
|
parser (>= 3.3.7.2)
|
||||||
prism (~> 1.4)
|
prism (~> 1.4)
|
||||||
|
rubocop-rspec (3.6.0)
|
||||||
|
lint_roller (~> 1.1)
|
||||||
|
rubocop (~> 1.72, >= 1.72.1)
|
||||||
rubocop-sequel (0.4.1)
|
rubocop-sequel (0.4.1)
|
||||||
lint_roller (~> 1.1)
|
lint_roller (~> 1.1)
|
||||||
rubocop (>= 1.72.1, < 2)
|
rubocop (>= 1.72.1, < 2)
|
||||||
ruby-progressbar (1.13.0)
|
ruby-progressbar (1.13.0)
|
||||||
ruby2_keywords (0.0.5)
|
ruby2_keywords (0.0.5)
|
||||||
sequel (5.92.0)
|
sequel (5.93.0)
|
||||||
bigdecimal
|
bigdecimal
|
||||||
sinatra (3.2.0)
|
sinatra (4.1.1)
|
||||||
|
logger (>= 1.6.0)
|
||||||
mustermann (~> 3.0)
|
mustermann (~> 3.0)
|
||||||
rack (~> 2.2, >= 2.2.4)
|
rack (>= 3.0.0, < 4)
|
||||||
rack-protection (= 3.2.0)
|
rack-protection (= 4.1.1)
|
||||||
|
rack-session (>= 2.0.0, < 3)
|
||||||
tilt (~> 2.0)
|
tilt (~> 2.0)
|
||||||
sinatra-contrib (3.2.0)
|
sinatra-contrib (4.1.1)
|
||||||
multi_json (>= 0.0.2)
|
multi_json (>= 0.0.2)
|
||||||
mustermann (~> 3.0)
|
mustermann (~> 3.0)
|
||||||
rack-protection (= 3.2.0)
|
rack-protection (= 4.1.1)
|
||||||
sinatra (= 3.2.0)
|
sinatra (= 4.1.1)
|
||||||
tilt (~> 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)
|
tilt (2.6.0)
|
||||||
unicode-display_width (3.1.4)
|
unicode-display_width (3.1.4)
|
||||||
unicode-emoji (~> 4.0, >= 4.0.4)
|
unicode-emoji (~> 4.0, >= 4.0.4)
|
||||||
unicode-emoji (4.0.4)
|
unicode-emoji (4.0.4)
|
||||||
|
|
||||||
PLATFORMS
|
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-gnu
|
||||||
|
x86_64-linux-musl
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
|
database_cleaner-sequel
|
||||||
logger
|
logger
|
||||||
ostruct
|
|
||||||
puma (~> 6.6)
|
puma (~> 6.6)
|
||||||
|
rack-test
|
||||||
rerun
|
rerun
|
||||||
|
rspec
|
||||||
rubocop
|
rubocop
|
||||||
|
rubocop-rspec
|
||||||
rubocop-sequel
|
rubocop-sequel
|
||||||
sequel (~> 5.92)
|
sequel (~> 5.92)
|
||||||
sinatra (~> 3.2)
|
sinatra (~> 4.1)
|
||||||
sinatra-contrib (~> 3.2)
|
sinatra-contrib (~> 4.1)
|
||||||
sqlite3 (~> 2.6)
|
sqlite3 (~> 2.6)
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
|
65
Gruntfile.js
65
Gruntfile.js
@@ -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']);
|
|
||||||
|
|
||||||
};
|
|
44
README.md
44
README.md
@@ -1,5 +1,7 @@
|
|||||||
# Game Data
|
# Game Data
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
Web-based tool to store and organize PC hardware gaming benchmarks.
|
Web-based tool to store and organize PC hardware gaming benchmarks.
|
||||||
|
|
||||||
## Project Goals
|
## Project Goals
|
||||||
@@ -7,28 +9,58 @@ Web-based tool to store and organize PC hardware gaming benchmarks.
|
|||||||
The goals of this project are to:
|
The goals of this project are to:
|
||||||
|
|
||||||
* Record benchmarking results from multiple devices - e.g. log from a laptop or a phone.
|
* Record benchmarking results from multiple devices - e.g. log from a laptop or a phone.
|
||||||
* Group results into tests - it's good practice to run a benchmark multiple times for accuracy.
|
* Group results into tests to keep track of different testing configurations.
|
||||||
|
* Encourage running tests multiple times - it's good practice to run a benchmark multiple times for accuracy.
|
||||||
* Create comparisons of hardware tests to compare performance.
|
* Create comparisons of hardware tests to compare performance.
|
||||||
* Generate graphs of hardware comparisons for usage in videos and articles.
|
* Generate graphs of hardware comparisons for usage in videos and articles.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
Game Data runs on Ruby, and takes advantage of Bundler to manage code dependencies and Rake to run various tasks for maintaining the app. You can install them globally like so:
|
Game Data runs on Ruby, and takes advantage of [Bundler](https://bundler.io/) to manage code dependencies and [Rake](https://ruby.github.io/rake/) to run various tasks for maintaining the app. You can install them globally like so:
|
||||||
|
|
||||||
Debian/Ubuntu: `apt install -y ruby ruby-bundler rake`
|
Debian/Ubuntu: `apt install -y ruby ruby-bundler rake`
|
||||||
|
RedHat and clones: `dnf install -y ruby rubygem-bundler rubygem-rake`
|
||||||
|
|
||||||
|
## Production Deployment
|
||||||
|
|
||||||
|
**TBD**
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
Install dependencies via bundler:
|
### Via Docker
|
||||||
|
|
||||||
|
If you'd prefer not to install dependencies and such to your local OS, you can do the development via Docker. The scripts provided in `bin/` will build Docker images for running the Ruby app and building the front-end assets via Gulp. *Both containers will automatically watch for changes.*
|
||||||
|
|
||||||
|
**Note:** Using the scripts below, the Docker images will remove themselves when stopped. This is to make clean up a bit more streamlined.
|
||||||
|
|
||||||
|
1. [Install Docker](https://docs.docker.com/engine/install/) for your OS.
|
||||||
|
|
||||||
|
2. Build the docker images for Ruby and Gulp:
|
||||||
|
|
||||||
|
`bin/docker-build.sh`
|
||||||
|
|
||||||
|
3. Run the docker images:
|
||||||
|
|
||||||
|
`bin/docker-run.sh`
|
||||||
|
|
||||||
|
4. If everything is running successfully you can open your browser and go to https://localhost:9292.
|
||||||
|
|
||||||
|
### Local/Native Development
|
||||||
|
|
||||||
|
1. Install dependencies via bundler:
|
||||||
|
|
||||||
`bundle install`
|
`bundle install`
|
||||||
|
|
||||||
Perform database migrations:
|
2. Perform database migrations:
|
||||||
|
|
||||||
`rake db:migrate`
|
`rake db:migrate`
|
||||||
|
|
||||||
Run the server in development with auto-reloading:
|
3. Run the server in development with auto-reloading:
|
||||||
|
|
||||||
`rake server:dev`
|
`rake server:dev`
|
||||||
|
|
||||||
If everything is running successfully you can open your browser and go to https://localhost:9292.
|
4. If everything is running successfully you can open your browser and go to https://localhost:9292.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is available under the BSD 2-Clause license.
|
||||||
|
24
Rakefile
24
Rakefile
@@ -3,29 +3,37 @@ require 'bundler/setup'
|
|||||||
namespace :db do
|
namespace :db do
|
||||||
desc 'Run migrations'
|
desc 'Run migrations'
|
||||||
task :migrate, [:version] do |t, args|
|
task :migrate, [:version] do |t, args|
|
||||||
require "sequel/core"
|
require 'sequel/core'
|
||||||
|
# load configuration
|
||||||
|
require_relative 'src/config'
|
||||||
|
conf = Config.new()
|
||||||
|
|
||||||
Sequel.extension :migration
|
Sequel.extension :migration
|
||||||
version = args[:version].to_i if args[:version]
|
version = args[:version].to_i if args[:version]
|
||||||
Sequel.connect('sqlite://data/gamedata.db') do |db|
|
Sequel.connect(adapter: conf.get('database.adapter'), database: conf.get('database.database')) do |db|
|
||||||
Sequel::Migrator.run(db, "db/migrations", target: version)
|
Sequel::Migrator.run(db, 'db/migrations', target: version)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
namespace :server do
|
namespace :server do
|
||||||
task :start do
|
task :start do
|
||||||
ENV['APP_ENV'] = 'production'
|
ENV['RACK_ENV'] = 'production'
|
||||||
system("puma")
|
system("puma")
|
||||||
end
|
end
|
||||||
|
|
||||||
task :dev do
|
task :dev do
|
||||||
system('rerun --no-notify --exit --dir="src/" puma')
|
system('rerun --no-notify --dir="src/" puma')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
namespace :test do
|
namespace :test do
|
||||||
task :rubocop do
|
task :unit do
|
||||||
system("rubocop src/")
|
ENV['RACK_ENV'] = 'testing'
|
||||||
|
system("rspec")
|
||||||
|
end
|
||||||
|
|
||||||
|
task :lint do
|
||||||
|
system("rubocop src/ spec/")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@ -1,2 +1,21 @@
|
|||||||
$ ->
|
$ ->
|
||||||
$(document).foundation()
|
# run foundation scripts
|
||||||
|
console.log('Ready.')
|
||||||
|
|
||||||
|
averageResults = (results, decimals = 2) ->
|
||||||
|
avgScore = 0
|
||||||
|
minScore = Infinity
|
||||||
|
maxScore = -Infinity
|
||||||
|
|
||||||
|
factor = (10 ^ decimals)
|
||||||
|
|
||||||
|
for result in results
|
||||||
|
avgScore += result.avg_score
|
||||||
|
minScore = Math.min(minScore, result.min_score)
|
||||||
|
maxScore = Math.max(maxScore, result.max_score)
|
||||||
|
|
||||||
|
return {
|
||||||
|
avgScore: Math.round((avgScore / results.length) * factor) / factor,
|
||||||
|
minScore: minScore,
|
||||||
|
maxScore: maxScore,
|
||||||
|
}
|
||||||
|
@@ -1,54 +1,109 @@
|
|||||||
$(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'),
|
$('#report-benchmarks').on 'change', (e) ->
|
||||||
type: 'horizontalBar'
|
$('#report-tests option').prop('selected', false)
|
||||||
data:
|
|
||||||
labels: []
|
$('#reports-download').on 'click', (e) ->
|
||||||
datasets: [
|
e.preventDefault()
|
||||||
{
|
canvas = $('#benchmark-chart')[0]
|
||||||
label: 'Average FPS'
|
a = document.createElement 'a'
|
||||||
data: []
|
a.href = canvas.toDataURL 'image/png'
|
||||||
backgroundColor: 'hotpink'
|
a.download = 'chart.png'
|
||||||
borderColor: '#212121'
|
a.click()
|
||||||
borderWidth: 1
|
|
||||||
}
|
$('#reports-button').on 'click', (e) ->
|
||||||
{
|
e.preventDefault()
|
||||||
label: 'Minimum FPS'
|
$('#reports-download').attr('disabled', true)
|
||||||
data: []
|
chartInstance.destroy() if chartInstance
|
||||||
backgroundColor: 'cornflowerblue'
|
|
||||||
borderColor: '#212121'
|
benchmarkId = $('#report-benchmarks').val()
|
||||||
borderWidth: 1
|
testIds = $('#report-tests').val()
|
||||||
}
|
|
||||||
]
|
benchmarkSearchParams = new URLSearchParams
|
||||||
options:
|
benchmark_id: benchmarkId
|
||||||
title:
|
benchmarkRes = await fetch("/api/v1/benchmark/details?#{benchmarkSearchParams}")
|
||||||
display: true
|
benchmarkData = await benchmarkRes.json()
|
||||||
text: 'N/a'
|
|
||||||
scales: xAxes: [ {
|
data =
|
||||||
display: true
|
labels: []
|
||||||
ticks: beginAtZero: true
|
datasets: []
|
||||||
} ]
|
|
||||||
animation: onComplete: ->
|
switch benchmarkData.scoring
|
||||||
dwnbtn = $('#download_button')
|
when 'pts'
|
||||||
dwnbtn.attr 'href', benchChart.toBase64Image()
|
data.datasets.push({
|
||||||
dwnbtn.attr 'download', 'benchmark_chart.png'
|
label: 'Average Score'
|
||||||
dwnbtn.attr 'disabled', false
|
data: []
|
||||||
return
|
})
|
||||||
)
|
when 'fps'
|
||||||
|
data.datasets.push({
|
||||||
|
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()
|
||||||
|
|
||||||
|
resultAverage = averageResults(resultData)
|
||||||
|
|
||||||
|
data.labels.push(testData.name)
|
||||||
|
data.datasets[0].data.push(resultAverage.avgScore)
|
||||||
|
console.log(data.datasets[0].data)
|
||||||
|
switch benchmarkData.scoring
|
||||||
|
when 'fps', 'ms'
|
||||||
|
data.datasets[1].data.push(resultAverage.minScore)
|
||||||
|
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')
|
||||||
|
44
assets/scripts/test.coffee
Normal file
44
assets/scripts/test.coffee
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
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/result/list?#{resultSearchParams}")
|
||||||
|
resultData = await resultRes.json()
|
||||||
|
|
||||||
|
resultAverage = averageResults(resultData)
|
||||||
|
|
||||||
|
tableRow = $("#results-table tr[data-benchmark-id=#{benchmarkId}]")
|
||||||
|
|
||||||
|
tableRow.append('<td><a href="/benchmark/' + benchmarkData.id + '">' + benchmarkData.name + '</a></td>')
|
||||||
|
tableRow.append('<td>' + benchmarkData.scoring + '</td>')
|
||||||
|
tableRow.append('<td>' + resultData.length + '</td>')
|
||||||
|
|
||||||
|
if resultData.length != 0
|
||||||
|
tableRow.append('<td>' + resultAverage.avgScore + '</td>')
|
||||||
|
|
||||||
|
if benchmarkData.scoring == 'fps'
|
||||||
|
tableRow.append('<td>' + resultAverage.minScore + '</td>')
|
||||||
|
tableRow.append('<td>' + resultAverage.maxScore + '</td>')
|
||||||
|
else
|
||||||
|
tableRow.append('<td>N/a</td>')
|
||||||
|
tableRow.append('<td>N/a</td>')
|
||||||
|
else
|
||||||
|
tableRow.append('<td>N/a</td>')
|
||||||
|
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)
|
||||||
|
)
|
@@ -1,5 +0,0 @@
|
|||||||
#main-nav
|
|
||||||
margin-bottom: 15px
|
|
||||||
|
|
||||||
h1.invalid
|
|
||||||
color: red
|
|
21
assets/styles/rimmington.sass
Normal file
21
assets/styles/rimmington.sass
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
@use "sass:color"
|
||||||
|
|
||||||
|
//$primary-color: #3399ff
|
||||||
|
$primary-color: cornflowerblue
|
||||||
|
$primary-color-highlight: color.adjust($primary-color, $lightness: -10%)
|
||||||
|
|
||||||
|
html
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
|
||||||
|
body
|
||||||
|
background: rgb(240, 235, 248)
|
||||||
|
|
||||||
|
table
|
||||||
|
border: 1px solid #666
|
||||||
|
|
||||||
|
#wrapper
|
||||||
|
background: white
|
||||||
|
padding: 1.5rem 2rem
|
||||||
|
border: 1px solid #bbb
|
||||||
|
border-radius: 8px
|
@@ -1 +1,2 @@
|
|||||||
docker build -t game-data -f Dockerfile.dev .
|
docker build -t game-data -f Dockerfile.dev .
|
||||||
|
docker build -t game-data-gulp -f Dockerfile.gulp .
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
docker build -t game-data -f Dockerfile.dev .
|
docker build -t game-data -f Dockerfile.dev .
|
||||||
|
docker build -t game-data-gulp -f Dockerfile.gulp .
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/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
|
||||||
|
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
# Load application config
|
# Load application config
|
||||||
require_relative 'src/config.rb'
|
|
||||||
$conf = Config.new(File.join(__dir__, 'config/defaults.yaml'))
|
|
||||||
|
|
||||||
root = ::File.dirname(__FILE__)
|
root = ::File.dirname(__FILE__)
|
||||||
require ::File.join( root, 'src', 'server' )
|
require ::File.join( root, 'src', 'server' )
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
database:
|
server:
|
||||||
adapter: 'sqlite'
|
host: '0.0.0.0'
|
||||||
database: 'data/gamedata.db'
|
port: '9292'
|
||||||
|
|
||||||
testing:
|
testing:
|
||||||
minimum_results_required: 3
|
minimum_results_required: 3
|
||||||
|
3
config/development.yaml
Normal file
3
config/development.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
database:
|
||||||
|
adapter: 'sqlite'
|
||||||
|
database: 'data/gamedata.db'
|
11
config/puma.rb
Normal file
11
config/puma.rb
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
app_dir = File.expand_path('..', __dir__)
|
||||||
|
directory app_dir
|
||||||
|
|
||||||
|
environment ENV.fetch('RACK_ENV', 'development')
|
||||||
|
|
||||||
|
require_relative '../src/config'
|
||||||
|
conf = Config.new()
|
||||||
|
|
||||||
|
bind "tcp://#{conf.get('server.host')}:#{conf.get('server.port')}"
|
||||||
|
workers 2
|
||||||
|
threads 1, 5
|
3
config/testing.yaml
Normal file
3
config/testing.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
database:
|
||||||
|
adapter: 'sqlite'
|
||||||
|
database: 'data/gamedata_testing.db'
|
39
db/migrations/0003_add_tests_table.rb
Normal file
39
db/migrations/0003_add_tests_table.rb
Normal 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
50
gulpfile.js
Normal 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
3004
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@@ -4,7 +4,7 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"main": "src/server.rb",
|
"main": "src/server.rb",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"grunt": "grunt"
|
"gulp": "gulp"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -18,11 +18,11 @@
|
|||||||
"author": "Gregory Ballantine <gballantine@bitgoblin.tech>",
|
"author": "Gregory Ballantine <gballantine@bitgoblin.tech>",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"grunt": "^1.6.1",
|
"gulp": "^5.0.1",
|
||||||
"grunt-cli": "^1.4.3",
|
"gulp-coffee": "^3.0.3",
|
||||||
"grunt-contrib-coffee": "^2.1.0",
|
"gulp-plumber": "^1.2.1",
|
||||||
"grunt-contrib-sass": "^2.0.0",
|
"gulp-sass": "^6.0.1",
|
||||||
"grunt-contrib-watch": "^1.1.0",
|
"gulp-sourcemaps": "^3.0.0",
|
||||||
"sass": "^1.77.4"
|
"sass": "^1.89.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
44
spec/controllers/benchmark_controller_spec.rb
Normal file
44
spec/controllers/benchmark_controller_spec.rb
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative '../spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe(BenchmarkController) do
|
||||||
|
# /benchmark - redirects to /benchmark/list
|
||||||
|
describe 'GET /benchmark' do
|
||||||
|
before { get '/benchmark' }
|
||||||
|
|
||||||
|
it 'Benchmark base route is a redirect' do
|
||||||
|
expect(last_response).to(be_redirect)
|
||||||
|
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
|
||||||
|
describe 'GET /benchmark/list' do
|
||||||
|
before { get '/benchmark/list' }
|
||||||
|
|
||||||
|
it 'Benchmark list page returns 200.' do
|
||||||
|
expect(last_response).to(be_ok)
|
||||||
|
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
|
||||||
|
describe 'GET /benchmark/add' do
|
||||||
|
before { get '/benchmark/add' }
|
||||||
|
|
||||||
|
it 'Benchmark add page returns 200.' do
|
||||||
|
expect(last_response).to(be_ok)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Benchmark add page contains 'Add new benchmark' on page." do
|
||||||
|
expect(last_response.body).to(include('Add new benchmark'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
44
spec/controllers/hardware_controller_spec.rb
Normal file
44
spec/controllers/hardware_controller_spec.rb
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative '../spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe(HardwareController) do
|
||||||
|
# /hardware - redirects to /hardware/list
|
||||||
|
describe 'GET /hardware' do
|
||||||
|
before { get '/hardware' }
|
||||||
|
|
||||||
|
it 'Hardware base route is a redirect' do
|
||||||
|
expect(last_response).to(be_redirect)
|
||||||
|
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
|
||||||
|
describe 'GET /hardware/list' do
|
||||||
|
before { get '/hardware/list' }
|
||||||
|
|
||||||
|
it 'Hardware list page returns 200.' do
|
||||||
|
expect(last_response).to(be_ok)
|
||||||
|
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
|
||||||
|
describe 'GET /hardware/add' do
|
||||||
|
before { get '/hardware/add' }
|
||||||
|
|
||||||
|
it 'Hardware add page returns 200.' do
|
||||||
|
expect(last_response).to(be_ok)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Hardware add page contains 'Add new hardware' on page." do
|
||||||
|
expect(last_response.body).to(include('Add new hardware'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
21
spec/controllers/index_controller_spec.rb
Normal file
21
spec/controllers/index_controller_spec.rb
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative '../spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe(IndexController) do
|
||||||
|
describe 'GET /' do
|
||||||
|
before { get '/' }
|
||||||
|
|
||||||
|
it 'Dashboard returns 200.' do
|
||||||
|
expect(last_response).to(be_ok)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Dashboard contains 'Game Data' on page (nav bar should be loaded)." do
|
||||||
|
expect(last_response.body).to(include('Game Data'))
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Dashboard contains 'Ruby version' on page (footer should be loaded)." do
|
||||||
|
expect(last_response.body).to(include('Ruby version'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
17
spec/controllers/reports_controller_spec.rb
Normal file
17
spec/controllers/reports_controller_spec.rb
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative '../spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe(ReportsController) do
|
||||||
|
describe 'GET /report' do
|
||||||
|
before { get '/report' }
|
||||||
|
|
||||||
|
it 'Reports page returns 200.' do
|
||||||
|
expect(last_response).to(be_ok)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Reports page contains 'Generate report' on page." do
|
||||||
|
expect(last_response.body).to(include('Generate report'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
44
spec/controllers/test_controller_spec.rb
Normal file
44
spec/controllers/test_controller_spec.rb
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative '../spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe(TestController) do
|
||||||
|
# /test - redirects to /test/list
|
||||||
|
describe 'GET /test' do
|
||||||
|
before { get '/test' }
|
||||||
|
|
||||||
|
it 'Test base route is a redirect' do
|
||||||
|
expect(last_response).to(be_redirect)
|
||||||
|
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
|
||||||
|
describe 'GET /test/list' do
|
||||||
|
before { get '/test/list' }
|
||||||
|
|
||||||
|
it 'Test list page returns 200.' do
|
||||||
|
expect(last_response).to(be_ok)
|
||||||
|
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
|
||||||
|
describe 'GET /test/add' do
|
||||||
|
before { get '/test/add' }
|
||||||
|
|
||||||
|
it 'Test add page returns 200.' do
|
||||||
|
expect(last_response).to(be_ok)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "Test add page contains 'Add new test' on page." do
|
||||||
|
expect(last_response.body).to(include('Add new test'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
27
spec/models/benchmark_model_spec.rb
Normal file
27
spec/models/benchmark_model_spec.rb
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative '../spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe(Benchmark) do
|
||||||
|
describe 'Benchmark Creation' do
|
||||||
|
it 'Benchmark creation updates model count.' do
|
||||||
|
expect do
|
||||||
|
described_class.create(name: 'Test Benchmark', scoring: 'fps')
|
||||||
|
end.to(change(described_class, :count).by(1))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'Benchmark Read' do
|
||||||
|
before { described_class.create(name: 'Test Benchmark', scoring: 'fps') }
|
||||||
|
|
||||||
|
it 'Benchmark model has name.' do
|
||||||
|
bench = described_class.first()
|
||||||
|
expect(bench.name).to(eq('Test Benchmark'))
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'Benchmark model has scoring.' do
|
||||||
|
bench = described_class.first()
|
||||||
|
expect(bench.scoring).to(eq('fps'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
25
spec/models/hardware_model_spec.rb
Normal file
25
spec/models/hardware_model_spec.rb
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative '../spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe(Hardware) do
|
||||||
|
describe 'Hardware Creation' do
|
||||||
|
it 'Hardware creation updates model count.' do
|
||||||
|
expect { described_class.create(name: 'Test Hardware', type: 'gpu') }.to(change(described_class, :count).by(1))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'Hardware Read' do
|
||||||
|
before { described_class.create(name: 'Test Hardware', type: 'gpu') }
|
||||||
|
|
||||||
|
it 'Hardware model has name.' do
|
||||||
|
hardware = described_class.first()
|
||||||
|
expect(hardware.name).to(eq('Test Hardware'))
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'Hardware model has scoring.' do
|
||||||
|
hardware = described_class.first()
|
||||||
|
expect(hardware.type).to(eq('gpu'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
36
spec/models/test_model_spec.rb
Normal file
36
spec/models/test_model_spec.rb
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative '../spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe(Test) do
|
||||||
|
describe 'Test Creation' do
|
||||||
|
it 'Test creation updates model count.' do
|
||||||
|
expect { described_class.create(name: 'Test Test') }.to(change(described_class, :count).by(1))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'Test Read' do
|
||||||
|
before do
|
||||||
|
described_class.create(name: 'Test Test')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'Test model has name.' do
|
||||||
|
tst = described_class.first()
|
||||||
|
expect(tst.name).to(eq('Test Test'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'Test one-to-many association with Hardware' do
|
||||||
|
it 'Test model has Hardware associated with it.' do
|
||||||
|
hardware = Hardware.create(name: 'Test Hardware', type: 'gpu')
|
||||||
|
tst = described_class.create(name: 'Test Test', hardware_id: hardware.id)
|
||||||
|
expect(tst.hardware).to(eq(hardware))
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'Test model\'s hardware has name set.' do
|
||||||
|
hardware = Hardware.create(name: 'Test Hardware', type: 'gpu')
|
||||||
|
tst = described_class.create(name: 'Test Test', hardware_id: hardware.id)
|
||||||
|
expect(tst.hardware.name).to(eq('Test Hardware'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
35
spec/spec_helper.rb
Normal file
35
spec/spec_helper.rb
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
ENV['APP_ENV'] = 'test'
|
||||||
|
|
||||||
|
require_relative '../src/server'
|
||||||
|
require 'rspec'
|
||||||
|
require 'rack/test'
|
||||||
|
require 'database_cleaner/sequel'
|
||||||
|
|
||||||
|
# setting this here so all redirect tests can reference the same base URL
|
||||||
|
BASE_URL = 'http://example.org'
|
||||||
|
|
||||||
|
module RSpecMixin
|
||||||
|
|
||||||
|
include Rack::Test::Methods
|
||||||
|
|
||||||
|
def app
|
||||||
|
GameData
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
RSpec.configure do |config|
|
||||||
|
config.include(RSpecMixin)
|
||||||
|
|
||||||
|
config.before(:suite) do
|
||||||
|
DatabaseCleaner.strategy = :transaction
|
||||||
|
end
|
||||||
|
|
||||||
|
config.around do |suite|
|
||||||
|
DatabaseCleaner.cleaning do
|
||||||
|
suite.run
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
7
src/appinfo.rb
Normal file
7
src/appinfo.rb
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module AppInfo
|
||||||
|
|
||||||
|
VERSION = '0.2.1'
|
||||||
|
|
||||||
|
end
|
@@ -6,8 +6,9 @@ require 'yaml'
|
|||||||
class Config
|
class Config
|
||||||
|
|
||||||
DEFAULT_CONFIG = 'config/defaults.yaml'
|
DEFAULT_CONFIG = 'config/defaults.yaml'
|
||||||
|
ENVIRONMENT_CONFIG = ENV.fetch('RACK_ENV', 'development')
|
||||||
|
|
||||||
def initialize(config_path)
|
def initialize(config_path = "config/#{ENVIRONMENT_CONFIG}.yaml")
|
||||||
@data = YAML.load_file(DEFAULT_CONFIG)
|
@data = YAML.load_file(DEFAULT_CONFIG)
|
||||||
|
|
||||||
# merge in user-defined configuration if it exists
|
# merge in user-defined configuration if it exists
|
||||||
|
38
src/controllers/api1.rb
Normal file
38
src/controllers/api1.rb
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'sinatra/json'
|
||||||
|
|
||||||
|
require_relative 'base_controller'
|
||||||
|
require_relative '../models/benchmark'
|
||||||
|
require_relative '../models/test'
|
||||||
|
require_relative '../models/result'
|
||||||
|
|
||||||
|
# /api/v1 routes
|
||||||
|
class APIv1Controller < BaseController
|
||||||
|
|
||||||
|
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/result/list' 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
|
||||||
|
|
||||||
|
get '/api/v1/test/details' do
|
||||||
|
test_id = params[:test_id]
|
||||||
|
|
||||||
|
tst = Test.where(id: test_id).first()
|
||||||
|
|
||||||
|
json tst.values()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
15
src/controllers/base_controller.rb
Normal file
15
src/controllers/base_controller.rb
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'sinatra/base'
|
||||||
|
|
||||||
|
# BaseController - base modular Sinatra app class
|
||||||
|
class BaseController < Sinatra::Base
|
||||||
|
|
||||||
|
# Register view helpers
|
||||||
|
require_relative '../helpers'
|
||||||
|
helpers Helpers
|
||||||
|
|
||||||
|
# Set up our view engine
|
||||||
|
set :views, File.join(settings.root, '/../../views')
|
||||||
|
|
||||||
|
end
|
65
src/controllers/benchmark.rb
Normal file
65
src/controllers/benchmark.rb
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative 'base_controller'
|
||||||
|
require_relative '../models/benchmark'
|
||||||
|
|
||||||
|
# /benchmark routes
|
||||||
|
class BenchmarkController < BaseController
|
||||||
|
|
||||||
|
get '/benchmark' do
|
||||||
|
redirect('/benchmark/list')
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/benchmark/list' do
|
||||||
|
benchmarks = Benchmark.reverse(:updated_at).limit(10).all()
|
||||||
|
|
||||||
|
erb :'benchmark/index', locals: {
|
||||||
|
title: 'List of Benchmarks',
|
||||||
|
benchmarks: benchmarks
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/benchmark/add' do
|
||||||
|
erb :'benchmark/add', locals: {
|
||||||
|
title: 'Add Benchmark'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
post '/benchmark/add' do
|
||||||
|
benchmark = Benchmark.create(
|
||||||
|
name: params[:benchmark_name],
|
||||||
|
scoring: params[:benchmark_scoring],
|
||||||
|
description: params[:benchmark_description]
|
||||||
|
)
|
||||||
|
|
||||||
|
redirect "/benchmark/#{benchmark.id}"
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/benchmark/:benchmark_id' do
|
||||||
|
benchmark = Benchmark.where(id: params[:benchmark_id]).first()
|
||||||
|
erb :'benchmark/view', locals: {
|
||||||
|
title: benchmark.name,
|
||||||
|
benchmark: benchmark
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/benchmark/:benchmark_id/edit' do
|
||||||
|
benchmark = Benchmark.where(id: params[:benchmark_id]).first()
|
||||||
|
erb :'benchmark/edit', locals: {
|
||||||
|
title: "Editing: #{benchmark.name}",
|
||||||
|
benchmark: benchmark
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
post '/benchmark/:benchmark_id/edit' do
|
||||||
|
benchmark = Benchmark.where(id: params[:benchmark_id]).first()
|
||||||
|
|
||||||
|
benchmark.update(
|
||||||
|
name: params[:benchmark_name],
|
||||||
|
scoring: params[:benchmark_scoring],
|
||||||
|
description: params[:benchmark_description]
|
||||||
|
)
|
||||||
|
|
||||||
|
redirect "/benchmark/#{benchmark.id}"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@@ -1,9 +1,17 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative 'base_controller'
|
||||||
|
require_relative '../models/hardware'
|
||||||
|
require_relative '../models/benchmark'
|
||||||
|
|
||||||
# /hardware routes
|
# /hardware routes
|
||||||
class GameData < Sinatra::Base
|
class HardwareController < BaseController
|
||||||
|
|
||||||
get '/hardware' do
|
get '/hardware' do
|
||||||
|
redirect('/hardware/list')
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/hardware/list' do
|
||||||
hardware = Hardware.reverse(:updated_at).limit(10).all()
|
hardware = Hardware.reverse(:updated_at).limit(10).all()
|
||||||
|
|
||||||
erb :'hardware/index', locals: {
|
erb :'hardware/index', locals: {
|
||||||
@@ -36,4 +44,23 @@ class GameData < Sinatra::Base
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
get '/hardware/:hardware_id/edit' do
|
||||||
|
hardware = Hardware.where(id: params[:hardware_id]).first()
|
||||||
|
erb :'hardware/edit', locals: {
|
||||||
|
title: "Editing: #{hardware.name}",
|
||||||
|
hardware: hardware
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
post '/hardware/: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
|
end
|
18
src/controllers/index.rb
Normal file
18
src/controllers/index.rb
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative 'base_controller'
|
||||||
|
require_relative '../models/test'
|
||||||
|
|
||||||
|
# / (top-level) routes
|
||||||
|
class IndexController < BaseController
|
||||||
|
|
||||||
|
get '/' do
|
||||||
|
tests = Test.reverse(:updated_at).limit(10).all()
|
||||||
|
|
||||||
|
erb :'index/index', locals: {
|
||||||
|
title: 'Dashboard',
|
||||||
|
tests: tests
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@@ -1,20 +1,27 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# /reports routes
|
require 'sinatra/json'
|
||||||
class GameData < Sinatra::Base
|
|
||||||
|
|
||||||
get '/reports' do
|
require_relative 'base_controller'
|
||||||
|
require_relative '../models/benchmark'
|
||||||
|
require_relative '../models/result'
|
||||||
|
require_relative '../models/test'
|
||||||
|
|
||||||
|
# /reports routes
|
||||||
|
class ReportsController < BaseController
|
||||||
|
|
||||||
|
get '/report' do
|
||||||
benchmarks = Benchmark.order(:name).all()
|
benchmarks = Benchmark.order(:name).all()
|
||||||
hardware = Hardware.order(:name).all()
|
tests = Test.order(:name).all()
|
||||||
|
|
||||||
erb :'reports/index', locals: {
|
erb :'reports/index', locals: {
|
||||||
title: 'Generate Reports',
|
title: 'Generate Reports',
|
||||||
hardware: hardware,
|
tests: tests,
|
||||||
benchmarks: benchmarks
|
benchmarks: benchmarks
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
post '/reports' do
|
post '/report' do
|
||||||
report_type = params[:type]
|
report_type = params[:type]
|
||||||
report_choice = params[:choice]
|
report_choice = params[:choice]
|
||||||
report_compare = params[:compare]
|
report_compare = params[:compare]
|
||||||
@@ -26,10 +33,10 @@ class GameData < Sinatra::Base
|
|||||||
min_results = []
|
min_results = []
|
||||||
|
|
||||||
report_compare.each do |c|
|
report_compare.each do |c|
|
||||||
hrd = Hardware.where(id: c).first()
|
tst = Test.where(id: c).first()
|
||||||
names.push(hrd.name)
|
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)
|
avg_results.push(res.avg_score)
|
||||||
min_results.push(res.min_score)
|
min_results.push(res.min_score)
|
||||||
end
|
end
|
@@ -1,33 +1,17 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative 'base_controller'
|
||||||
|
require_relative '../models/result'
|
||||||
|
|
||||||
# /result routes
|
# /result routes
|
||||||
class GameData < Sinatra::Base
|
class ResultController < BaseController
|
||||||
|
|
||||||
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
|
post '/result/add' do
|
||||||
result_minimum = params[:result_minimum] if params.key?(:result_minimum)
|
result_minimum = params[:result_minimum] if params.key?(:result_minimum)
|
||||||
result_maximum = params[:result_maximum] if params.key?(:result_maximum)
|
result_maximum = params[:result_maximum] if params.key?(:result_maximum)
|
||||||
|
|
||||||
Result.create(
|
Result.create(
|
||||||
hardware_id: params[:result_hardware],
|
test_id: params[:result_test],
|
||||||
benchmark_id: params[:result_benchmark],
|
benchmark_id: params[:result_benchmark],
|
||||||
avg_score: params[:result_average],
|
avg_score: params[:result_average],
|
||||||
min_score: result_minimum,
|
min_score: result_minimum,
|
||||||
@@ -35,8 +19,8 @@ class GameData < Sinatra::Base
|
|||||||
)
|
)
|
||||||
|
|
||||||
if params.key?(:result_referrer)
|
if params.key?(:result_referrer)
|
||||||
if params[:result_referrer] == 'hardware'
|
if params[:result_referrer] == 'test'
|
||||||
redirect "/hardware/#{params[:result_hardware]}"
|
redirect "/test/#{params[:result_test]}"
|
||||||
elsif params[:result_referrer] == 'benchmark'
|
elsif params[:result_referrer] == 'benchmark'
|
||||||
redirect "/benchmark/#{params[:result_benchmark]}"
|
redirect "/benchmark/#{params[:result_benchmark]}"
|
||||||
end
|
end
|
96
src/controllers/test.rb
Normal file
96
src/controllers/test.rb
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative 'base_controller'
|
||||||
|
require_relative '../models/benchmark'
|
||||||
|
require_relative '../models/hardware'
|
||||||
|
require_relative '../models/test'
|
||||||
|
|
||||||
|
# /test routes
|
||||||
|
class TestController < BaseController
|
||||||
|
|
||||||
|
get '/test' do
|
||||||
|
redirect('/test/list')
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/test/list' 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/:test_id/edit' do
|
||||||
|
tst = Test.where(id: params[:test_id]).first()
|
||||||
|
hardware = Hardware.order(:name).all()
|
||||||
|
benchmarks = Benchmark.order(:name).all()
|
||||||
|
|
||||||
|
erb :'test/edit', locals: {
|
||||||
|
title: "Editing: #{tst.name}",
|
||||||
|
test: tst,
|
||||||
|
hardware: hardware,
|
||||||
|
benchmarks: benchmarks
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
post '/test/:test_id/edit' do
|
||||||
|
tst = Test.where(id: params[:test_id]).first()
|
||||||
|
|
||||||
|
tst.update(
|
||||||
|
name: params[:test_name],
|
||||||
|
hardware_id: params[:test_hardware],
|
||||||
|
description: params[:test_description]
|
||||||
|
)
|
||||||
|
|
||||||
|
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)
|
||||||
|
end
|
||||||
|
|
||||||
|
# associate the benchmarks to the test
|
||||||
|
selected_benchmarks.each do |b|
|
||||||
|
tst.add_benchmark(b) unless tst.benchmark?(b)
|
||||||
|
end
|
||||||
|
|
||||||
|
redirect "/test/#{tst.id}"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@@ -1,8 +1,18 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative 'appinfo'
|
||||||
|
|
||||||
# Helpers - view helper functions
|
# Helpers - view helper functions
|
||||||
module Helpers
|
module Helpers
|
||||||
|
|
||||||
|
def ruby_version
|
||||||
|
return RUBY_VERSION
|
||||||
|
end
|
||||||
|
|
||||||
|
def app_version
|
||||||
|
return AppInfo::VERSION
|
||||||
|
end
|
||||||
|
|
||||||
def date_format(date)
|
def date_format(date)
|
||||||
dt = date.to_datetime
|
dt = date.to_datetime
|
||||||
return dt.strftime('%B %d, %Y @ %I:%M:%S %p %Z')
|
return dt.strftime('%B %d, %Y @ %I:%M:%S %p %Z')
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
# Benchmark - database model for PC benchmarks
|
# Benchmark - database model for PC benchmarks
|
||||||
class Benchmark < Sequel::Model
|
class Benchmark < Sequel::Model
|
||||||
|
|
||||||
|
many_to_many :tests
|
||||||
one_to_many :results
|
one_to_many :results
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
# Hardware - database model for PC hardware
|
# Hardware - database model for PC hardware
|
||||||
class Hardware < Sequel::Model(:hardware)
|
class Hardware < Sequel::Model(:hardware)
|
||||||
|
|
||||||
one_to_many :results
|
one_to_many :tests
|
||||||
|
|
||||||
def bench_results
|
def bench_results
|
||||||
br = {}
|
br = {}
|
||||||
|
@@ -1,5 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require_relative 'hardware'
|
|
||||||
require_relative 'benchmark'
|
|
||||||
require_relative 'result'
|
|
@@ -3,7 +3,7 @@
|
|||||||
# Result - database model for benchmark results
|
# Result - database model for benchmark results
|
||||||
class Result < Sequel::Model
|
class Result < Sequel::Model
|
||||||
|
|
||||||
many_to_one :hardware
|
many_to_one :test
|
||||||
many_to_one :benchmark
|
many_to_one :benchmark
|
||||||
|
|
||||||
def formatted_score
|
def formatted_score
|
||||||
|
14
src/models/test.rb
Normal file
14
src/models/test.rb
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# 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 :benchmarks
|
||||||
|
|
||||||
|
def benchmark?(benchmark_id)
|
||||||
|
return benchmarks_dataset.where(Sequel[:benchmarks][:id] => benchmark_id).any?
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@@ -1,30 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
# /benchmark routes
|
|
||||||
class GameData < Sinatra::Base
|
|
||||||
|
|
||||||
get '/benchmark' do
|
|
||||||
benchmarks = Benchmark.reverse(:updated_at).limit(10).all()
|
|
||||||
|
|
||||||
erb :'benchmark/index', locals: {
|
|
||||||
title: 'List of Benchmarks',
|
|
||||||
benchmarks: benchmarks
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/benchmark/add' do
|
|
||||||
erb :'benchmark/add', locals: {
|
|
||||||
title: 'Add Benchmark'
|
|
||||||
}
|
|
||||||
end
|
|
||||||
post '/benchmark/add' do
|
|
||||||
benchmark = Benchmark.create(
|
|
||||||
name: params[:benchmark_name],
|
|
||||||
scoring: params[:benchmark_scoring],
|
|
||||||
description: params[:benchmark_description]
|
|
||||||
)
|
|
||||||
|
|
||||||
redirect "/benchmark/#{benchmark.id}"
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
@@ -1,15 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
# / (top-level) routes
|
|
||||||
class GameData < Sinatra::Base
|
|
||||||
|
|
||||||
get '/' do
|
|
||||||
results = Result.reverse(:updated_at).limit(10).all()
|
|
||||||
|
|
||||||
erb :'index/index', locals: {
|
|
||||||
title: 'Dashboard',
|
|
||||||
results: results
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
@@ -1,7 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require_relative 'index'
|
|
||||||
require_relative 'hardware'
|
|
||||||
require_relative 'benchmark'
|
|
||||||
require_relative 'result'
|
|
||||||
require_relative 'reports'
|
|
38
src/server.rb
Executable file → Normal file
38
src/server.rb
Executable file → Normal file
@@ -1,16 +1,32 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'sinatra/base'
|
require 'sinatra/base'
|
||||||
require 'sinatra/json'
|
|
||||||
require 'sequel'
|
require 'sequel'
|
||||||
require 'sqlite3'
|
require 'sqlite3'
|
||||||
|
|
||||||
|
require_relative 'config'
|
||||||
|
|
||||||
|
# Load configuration from environment config file
|
||||||
|
$conf = Config.new()
|
||||||
|
|
||||||
# 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
|
||||||
DB = Sequel.connect(adapter: $conf.get('database.adapter'), database: $conf.get('database.database'))
|
DB = Sequel.connect(adapter: $conf.get('database.adapter'), database: $conf.get('database.database'))
|
||||||
|
|
||||||
# Base app
|
# Load in routes (must happen after Sequel is loaded!)
|
||||||
|
require_relative 'controllers/api1'
|
||||||
|
require_relative 'controllers/benchmark'
|
||||||
|
require_relative 'controllers/hardware'
|
||||||
|
require_relative 'controllers/index'
|
||||||
|
require_relative 'controllers/reports'
|
||||||
|
require_relative 'controllers/result'
|
||||||
|
require_relative 'controllers/test'
|
||||||
|
|
||||||
|
# GameData - main app that gets launched
|
||||||
|
# - inherits from Sinatra::Base to instantiate the server
|
||||||
|
# - sets up some base app configuration
|
||||||
|
# - registers route classes with the base app
|
||||||
class GameData < Sinatra::Base
|
class GameData < Sinatra::Base
|
||||||
|
|
||||||
enable :sessions
|
enable :sessions
|
||||||
@@ -19,16 +35,12 @@ class GameData < Sinatra::Base
|
|||||||
enable :static
|
enable :static
|
||||||
set :public_folder, File.join(__dir__, '/../public')
|
set :public_folder, File.join(__dir__, '/../public')
|
||||||
|
|
||||||
# Register view helpers
|
use IndexController
|
||||||
require_relative 'helpers'
|
use HardwareController
|
||||||
helpers Helpers
|
use BenchmarkController
|
||||||
|
use TestController
|
||||||
# Set up our view engine
|
use ResultController
|
||||||
set :views, File.join(settings.root, '/../views')
|
use ReportsController
|
||||||
|
use APIv1Controller
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Load routes
|
|
||||||
require_relative 'routes/init'
|
|
||||||
# Load models
|
|
||||||
require_relative 'models/init'
|
|
||||||
|
@@ -1,41 +1,38 @@
|
|||||||
<div class="grid-x grid-margin-x">
|
<div class="row mb-4">
|
||||||
<div class="cell small-12">
|
<div class="col-12">
|
||||||
<h1>Add new benchmark</h1>
|
<h1>Add new benchmark</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid-x grid-margin-x">
|
<div class="row">
|
||||||
|
|
||||||
<form class="cell small-12" action="/benchmark/add" method="post">
|
<form class="col-12" action="/benchmark/add" method="post">
|
||||||
<div class="grid-x grid-padding-x">
|
<div class="row mb-3">
|
||||||
<div class="cell medium-9">
|
<div class="col-9">
|
||||||
<label>
|
<label for="benchmark_name">Benchmark name</label>
|
||||||
Benchmark name
|
<input id="benchmark_name" class="form-control" type="text" name="benchmark_name" placeholder="Example benchmark">
|
||||||
<input type="text" name="benchmark_name" placeholder="Example benchmark">
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="cell medium-3">
|
<div class="col-3">
|
||||||
<label>
|
<label for="benchmark_scoring">Scoring type</label>
|
||||||
Scoring type
|
<select id="benchmark_scoring" class="form-select" name="benchmark_scoring">
|
||||||
<select name="benchmark_scoring">
|
<option value="fps">Frames per Second (fps)</option>
|
||||||
<option value="fps">Frames per Second (fps)</option>
|
<option value="ms">Frame Time (ms)</option>
|
||||||
<option value="ms">Frame Time (ms)</option>
|
<option value="pts">Total Points</option>
|
||||||
<option value="pts">Total Points</option>
|
</select>
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid-x grid-padding-x">
|
<div class="row mb-3">
|
||||||
<div class="cell small-12">
|
<div class="col-12">
|
||||||
<textarea name="benchmark_description" class="cell small-12">Enter a description/notes here.</textarea>
|
<label for="benchmark_description">Benchmark description</label>
|
||||||
|
<textarea id="benchmark_description" class="form-control" name="benchmark_description" placeholder="Enter a description/notes here."></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid-x grid-padding-x">
|
<div class="row">
|
||||||
<div class="cell small-12">
|
<div class="col-12">
|
||||||
<input type="submit" class="button" value="Submit">
|
<input class="btn btn-primary w-100" type="submit" value="Create Benchmark">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
40
views/benchmark/edit.erb
Normal file
40
views/benchmark/edit.erb
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<div class="row mb-4">
|
||||||
|
<div class="col-12">
|
||||||
|
<h1>Editing: <%= benchmark.name %></h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<form class="cell small-12" action="/benchmark/<%= benchmark.id %>/edit" 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" value="<%= benchmark.name %>">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<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="row mb-3">
|
||||||
|
<div class="col-12">
|
||||||
|
<label for="benchmark_description">Benchmark description</label>
|
||||||
|
<textarea id="benchmark_description" class="form-control" name="benchmark_description" placeholder="Enter a description/notes here."><%= benchmark.description %></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<input class="btn btn-primary w-100" type="submit" value="Submit Changes">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
@@ -1,41 +1,39 @@
|
|||||||
<div class="grid-x grid-margin-x">
|
<div class="row mb-3">
|
||||||
<div class="cell small-12">
|
<div class="col-12">
|
||||||
<h1>List of benchmarks</h1>
|
<h1>List of benchmarks</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="cell small-12">
|
<div class="col-12">
|
||||||
<p>
|
<p>
|
||||||
<a href="/benchmark/add">Add new benchmark</a>
|
<a href="/benchmark/add">Add new benchmark</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid-x grid-margin-x">
|
<div class="row">
|
||||||
<% if benchmarks.length > 0 %>
|
<% if benchmarks.length > 0 %>
|
||||||
<div class="cell small-12">
|
<div class="col-12">
|
||||||
<table>
|
<table class="table table-hover table-responsive">
|
||||||
<thead>
|
<thead class="table-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Benchmark name</th>
|
<th>Benchmark name</th>
|
||||||
<th>Scoring type</th>
|
<th>Scoring type</th>
|
||||||
<th>Date added</th>
|
<th>Notes</th>
|
||||||
<th>Date modified</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<% benchmarks.each do |b| %>
|
<% benchmarks.each do |b| %>
|
||||||
<tr>
|
<tr>
|
||||||
<td><%= b.name %></td>
|
<td><a href="/benchmark/<%= b.id %>"><%= b.name %></a></td>
|
||||||
<td><%= b.scoring %></td>
|
<td><%= b.scoring %></td>
|
||||||
<td><%= date_format(b.created_at) %></td>
|
<td><%= b.description %></td>
|
||||||
<td><%= date_format(b.updated_at) %></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% 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>
|
<p>I'm sorry, there doesn't appear to be any benchmarks added yet. Check again later!</p>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
49
views/benchmark/view.erb
Normal file
49
views/benchmark/view.erb
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h1><%= benchmark.name %></h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12">
|
||||||
|
<p><a href="/benchmark/<%= benchmark.id %>/edit">Edit</a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12">
|
||||||
|
Benchmark scoring type: <%= benchmark.scoring %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12">
|
||||||
|
Description:
|
||||||
|
<p><%= benchmark.description %></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h3 class="mb-3">Tests using this benchmark:</h3>
|
||||||
|
|
||||||
|
<% if benchmark.tests.length > 0 %>
|
||||||
|
<table class="table table-hover table-responsive">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>Test title</th>
|
||||||
|
<th>Benchmarks</th>
|
||||||
|
<th>Last updated</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% benchmark.tests.each do |t| %>
|
||||||
|
<tr>
|
||||||
|
<td><a href="/test/<%= t.id %>"><%= t.name %></a></td>
|
||||||
|
<td><%= t.benchmarks.length %></td>
|
||||||
|
<td><%= t.updated_at %></td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<% else %>
|
||||||
|
<p>There are no tests associated with this benchmark.</p>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -1,32 +1,32 @@
|
|||||||
<div class="grid-x grid-margin-x">
|
<div class="row mb-3">
|
||||||
<div class="cell small-12">
|
<div class="col-12">
|
||||||
<h1>Add new hardware</h1>
|
<h1>Add new hardware</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid-x grid-margin-x">
|
<div class="row mb-3">
|
||||||
|
|
||||||
<form class="cell small-12" action="/hardware/add" method="post">
|
<form class="col-12" action="/hardware/add" method="post">
|
||||||
<div class="grid-x grid-padding-x">
|
<div class="row mb-3">
|
||||||
<div class="cell medium-9">
|
<div class="col-12 col-md-9">
|
||||||
<label>
|
<label for="hardware_name">Hardware name</label>
|
||||||
Hardware name
|
<input id="hardware_name" class="form-control" type="text" name="hardware_name" placeholder="Example hardware">
|
||||||
<input type="text" name="hardware_name" placeholder="Example hardware">
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="cell medium-3">
|
<div class="col-12 col-md-3">
|
||||||
<label>
|
<label for="hardware_type">Type</label>
|
||||||
Type
|
<select id="hardware_type" class="form-select" name="hardware_type">
|
||||||
<select name="hardware_type">
|
<option value="gpu">Graphics card</option>
|
||||||
<option value="gpu">Graphics card</option>
|
<option value="cpu">Processor</option>
|
||||||
<option value="cpu">Processor</option>
|
</select>
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="submit" class="button" value="Submit">
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<input class="btn btn-primary w-100" type="submit" value="Create Hardware">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
32
views/hardware/edit.erb
Normal file
32
views/hardware/edit.erb
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-12">
|
||||||
|
<h1>Add new hardware</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
|
||||||
|
<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="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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<input class="btn btn-primary w-100" type="submit" value="Submit Changes">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
@@ -1,20 +1,20 @@
|
|||||||
<div class="grid-x grid-margin-x">
|
<div class="row mb-3">
|
||||||
<div class="cell small-12">
|
<div class="col-12">
|
||||||
<h1>List of hardware</h1>
|
<h1>List of hardware</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="cell small-12">
|
<div class="col-12">
|
||||||
<p>
|
<p>
|
||||||
<a href="/hardware/add">Add new hardware</a>
|
<a href="/hardware/add">Add new hardware</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid-x grid-margin-x">
|
<div class="row mb-3">
|
||||||
<% if hardware.length > 0 %>
|
<% if hardware.length > 0 %>
|
||||||
<div class="cell small-12">
|
<div class="col-12">
|
||||||
<table>
|
<table class="table table-hover table-responsive">
|
||||||
<thead>
|
<thead class="table-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Hardware name</th>
|
<th>Hardware name</th>
|
||||||
<th>Type</th>
|
<th>Type</th>
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% 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>
|
<p>I'm sorry, there doesn't appear to be any hardware added yet. Check again later!</p>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
@@ -1,85 +1,44 @@
|
|||||||
<div class="grid-x grid-margin-x">
|
<div class="row">
|
||||||
<div class="cell small-12">
|
<div class="col-12">
|
||||||
<h1><%= hardware.name %></h1>
|
<h1><%= hardware.name %></h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="cell small-12">
|
<div class="col-12">
|
||||||
|
<p><a href="/hardware/<%= hardware.id %>/edit">Edit</a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12">
|
||||||
Hardware type: <%= hardware.type %>
|
Hardware type: <%= hardware.type %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div class="grix-x grix-margin-x">
|
<div class="row">
|
||||||
<div class="cell small-12">
|
<div class="col-12">
|
||||||
<form class="u-full-width" action="/result/add" method="post">
|
<h3 class="mb-3">Tests using this benchmark:</h3>
|
||||||
<input type="hidden" name="result_hardware" value="<%= hardware.id %>">
|
|
||||||
<input type="hidden" name="result_referrer" value="hardware">
|
|
||||||
|
|
||||||
<div class="grid-x grid-margin-x">
|
<% if hardware.tests.length > 0 %>
|
||||||
<div class="cell medium-5">
|
<table class="table table-hover table-responsive">
|
||||||
<label for="result_benchmark">
|
<thead class="table-light">
|
||||||
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>
|
<tr>
|
||||||
<td><%= k %></td>
|
<th>Test title</th>
|
||||||
<td>N/a</td>
|
<th>Benchmarks</th>
|
||||||
<td><%= r.length %></td>
|
<th>Last updated</th>
|
||||||
<td><%= average_array(r) %></td>
|
|
||||||
<td>N/a</td>
|
|
||||||
<td>N/a</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
</thead>
|
||||||
</tbody>
|
<tbody>
|
||||||
</table>
|
<% hardware.tests.each do |t| %>
|
||||||
|
<tr>
|
||||||
|
<td><a href="/test/<%= t.id %>"><%= t.name %></a></td>
|
||||||
|
<td><%= t.benchmarks.length %></td>
|
||||||
|
<td><%= t.updated_at %></td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<% else %>
|
||||||
|
<p>There are no tests associated with this benchmark.</p>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,30 +1,31 @@
|
|||||||
<div class="grid-x grid-margin-x">
|
<div class="row">
|
||||||
<% if results.length > 0 %>
|
<% if tests.length > 0 %>
|
||||||
<div class="cell small-12">
|
<div class="12-col mb-3">
|
||||||
<h2>Latest benchmark results:</h2>
|
<h2>Latest benchmark results:</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="cell small-12">
|
|
||||||
<table>
|
<div class="12-col">
|
||||||
<thead>
|
<table class="table table-hover table-responsive">
|
||||||
|
<thead class="table-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Hardware tested</th>
|
<th>Test name</th>
|
||||||
<th>Benchmark used</th>
|
<th># Benchmarks</th>
|
||||||
<th>Score</th>
|
<th>Last Updated</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<% results.each do |r| %>
|
<% tests.each do |t| %>
|
||||||
<tr>
|
<tr>
|
||||||
<td><%= r.hardware.name %></td>
|
<td><a href="/test/<%= t.id %>"><%= t.name %></a></td>
|
||||||
<td><%= r.benchmark.name %></td>
|
<td><%= t.benchmarks.length %></td>
|
||||||
<td><%= r.formatted_score() %></td>
|
<td><%= t.updated_at %></td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
<div class="cell small-12">
|
<div class="12-col">
|
||||||
<p>I'm sorry, there don't appear to be any benchmark results logged yet. Check again later!</p>
|
<p>I'm sorry, there don't appear to be any benchmark results logged yet. Check again later!</p>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
@@ -5,20 +5,24 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
<title><%= title %> | Game Data</title>
|
<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="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.7/css/bootstrap.min.css">
|
||||||
<link rel="stylesheet" href="/css/remmington.css">
|
<link rel="stylesheet" href="/css/rimmington.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/jquery/3.7.1/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>
|
<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 class="grid-container">
|
<main class="flex-grow-1 py-4">
|
||||||
<%= yield %>
|
<div id="wrapper" class="container mb-4">
|
||||||
</div>
|
<%= yield %>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- site footer -->
|
||||||
|
<%= erb :'partials/footer', :locals => locals %>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
10
views/partials/footer.erb
Normal file
10
views/partials/footer.erb
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<footer id="main-footer" class="bg-light border-top py-3 text-center">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<p>Game Data version v<%= app_version() %></p>
|
||||||
|
<p class="mb-0">Running Ruby version v<%= ruby_version() %></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
@@ -1,11 +1,29 @@
|
|||||||
<div id="main-nav" class="top-bar">
|
<div id="main-nav" class="navbar navbar-expand-md bg-dark border-bottom border-body mb-3" data-bs-theme="dark">
|
||||||
<div class="top-bar-left">
|
<div class="container-fluid">
|
||||||
<ul class="menu">
|
<a class="navbar-brand mb-0 h1" href="#">Game Data</a>
|
||||||
<li><a href="/">Dashboard</a></li>
|
|
||||||
<li><a href="/hardware">Hardware</a></li>
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<li><a href="/benchmark">Benchmarks</a></li>
|
<span class="navbar-toggler-icon"></span>
|
||||||
<li><a href="/result">Results</a></li>
|
</button>
|
||||||
<li><a href="/reports">Reports</a></li>
|
|
||||||
</ul>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,35 +1,49 @@
|
|||||||
<div class="grid-x grid-margin-x">
|
<div class="row">
|
||||||
<form class="cell small-12" action="/reports" method="post">
|
<div class="col-12">
|
||||||
<div class="grid-x grid-margin-x">
|
<h1>Generate report</h1>
|
||||||
<select class="cell medium-6" id="report_type" name="report_type" disabled>
|
</div>
|
||||||
<option value="benchmark">Benchmark</option>
|
</div>
|
||||||
<option value="hardware">Hardware</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select class="cell medium-6" id="report_choice" name="report_choice">
|
<div class="row">
|
||||||
<% benchmarks.each do |b| %>
|
<form class="col-12" action="/reports" method="post">
|
||||||
<option value="<%= b.id %>"><%= b.name %></option>
|
<div class="row mb-3">
|
||||||
|
<div class="col-12 col-md-6">
|
||||||
|
<select id="report-type" class="form-select" name="report_type" disabled>
|
||||||
|
<option value="benchmark">Benchmark</option>
|
||||||
|
<option value="test">Test</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 col-md-6">
|
||||||
|
<select id="report-benchmarks" class="form-select" name="report_choice">
|
||||||
|
<% benchmarks.each do |b| %>
|
||||||
|
<option value="<%= b.id %>"><%= b.name %></option>
|
||||||
|
<% end %>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 mb-3">
|
||||||
|
<select id="report-tests" class="col-12 form-select" name="report_compare[]" multiple>
|
||||||
|
<% tests.each do |t| %>
|
||||||
|
<option value="<%= t.id %>"><%= t.name %></option>
|
||||||
<% end %>
|
<% end %>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid-x grid-margin-x">
|
<div class="col-12 mb-3">
|
||||||
<select class="cell small-12" id="report_compare" name="report_compare[]" multiple>
|
<button id="reports-button" class="btn btn-primary">Generate</button>
|
||||||
<% hardware.each do |h| %>
|
<button id="reports-download" class="btn btn-primary" disabled>Download</button>
|
||||||
<option value="<%= h.id %>"><%= h.name %></option>
|
|
||||||
<% end %>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="submit" class="button" id="generate_button" value="Generate">
|
<div class="col-12">
|
||||||
<a href="#" class="button" id="download_button" disabled>Download</a>
|
<canvas id="benchmark-chart" width="100%" height="25"></canvas>
|
||||||
|
|
||||||
<div class="grid-x grid-margin-x">
|
|
||||||
<canvas id="chart_canvas" 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>
|
||||||
|
@@ -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>
|
|
@@ -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>
|
|
49
views/test/add.erb
Normal file
49
views/test/add.erb
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<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-0 mb-md-3">
|
||||||
|
<div class="col-12 col-md-6 mb-3 mb-md-0">
|
||||||
|
<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 mb-md-0">
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<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..."></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<input class="btn btn-primary w-100" type="submit" value="Create Test">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
49
views/test/edit.erb
Normal file
49
views/test/edit.erb
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-12">
|
||||||
|
<h1>Editing: <%= test.name %></h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<form class="col-12" action="/test/<%= test.id %>/edit" method="post">
|
||||||
|
<div class="row mb-0 mb-md-3">
|
||||||
|
<div class="col-12 col-md-6 mb-3 mb-md-0">
|
||||||
|
<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)" value="<%= test.name %>">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 col-md-6 mb-3 mb-md-0">
|
||||||
|
<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 %>" <% if h.id == test.hardware.id %>selected<% end %>><%= h.name %></option>
|
||||||
|
<% end %>
|
||||||
|
</select>
|
||||||
|
</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 %>" <% if test.benchmark?(b.id) %>selected<% end %>><%= 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="col-12">
|
||||||
|
<input class="btn btn-primary w-100" type="submit" value="Submit Changes">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
42
views/test/index.erb
Normal file
42
views/test/index.erb
Normal 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.benchmarks.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>
|
83
views/test/view.erb
Normal file
83
views/test/view.erb
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h1><%= test.name %></h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12">
|
||||||
|
<p><a href="/test/<%= test.id %>/edit">Edit</a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12">
|
||||||
|
<p>Hardware tested: <a href="/hardware/<%= test.hardware.id %>"><%= test.hardware.name %></a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12">
|
||||||
|
<p><%= test.description %></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<form action="/result/add" method="post">
|
||||||
|
<input type="hidden" name="result_test" value="<%= test.id %>">
|
||||||
|
<input type="hidden" name="result_referrer" value="test">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<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>
|
||||||
|
<% end %>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-4 col-md-2">
|
||||||
|
<label for="result_average">Average score:</label>
|
||||||
|
<input id="result_average" class="form-control" type="text" name="result_average" value="">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-4 col-md-2">
|
||||||
|
<label for="result_minimum">Minimum score:</label>
|
||||||
|
<input id="result_minimum" class="form-control" type="text" name="result_minimum" value="">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-4 col-md-2 mb-3 mb-md-0">
|
||||||
|
<label for="result_maximum">Maximum score:</label>
|
||||||
|
<input id="result_maximum" class="form-control" type="text" name="result_maximum" value="">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 col-md-1 d-flex align-items-stretch mb-3 mb-md-0">
|
||||||
|
<input class="btn btn-primary w-100" type="submit" value="Submit">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h4>Benchmark results for this test:</h4>
|
||||||
|
|
||||||
|
<table id="results-table" class="table table-hover table-responsive" data-test-id="<%= test.id %>">
|
||||||
|
<thead class="table-light">
|
||||||
|
<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.benchmarks.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>
|
Reference in New Issue
Block a user