sciolyff-duosmium 0.13.0 → 0.13.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f8d723a4b5265cf85a60231c83d8f1eeea0558cc0f6c8f2e51572bca2a86e6f
4
- data.tar.gz: b733acad947c8c180011279e4681c086bc94d78efb920433f6e0d72333c3b8e9
3
+ metadata.gz: 4a7b4a31efaca54ca04e7eb901a3681f3f66545a1830a909b8a362aa95b7180c
4
+ data.tar.gz: 347bde8ec63fb0bee0d82fd0ddb20af7004ce17aa3d12e77bd74a80e81a20d00
5
5
  SHA512:
6
- metadata.gz: 62fddbdf4bb9e9e953678a9cf87487c9f68b97b082cc9be825f384933ae06093923dfbc1966aa7c1a5f8ff7fd60107216f43ef9014fb09d5d57b6eba9fff76cb
7
- data.tar.gz: beef2bd6cad0cf430f7699b515a85459881ef1c3f4602ef622046e2f62024d52917eafe63418aa27825ea8dc41c5aa1601b57c327b8376456940c001e17816cf
6
+ metadata.gz: '0119ec1439da52ad630dd29c28233f4b266b42c0e2bc5ee8e514274854c10f2e145406b45f946cabeafb5857c124abc90aad7a75bbcacc83dcf57646b0010829'
7
+ data.tar.gz: 69a80f6ec3c9d1eac8bfe3fd17de028eb999ac29db7630c5c859cd92f9263f1eaf4e0ae64bc6932b28791adf5daa56c9efb802bbcfdeec5649b009aa98405ec0
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # SciolyFF (Science Olympiad File Format)
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/sciolyff.svg)](https://badge.fury.io/rb/sciolyff)
3
+ [![Gem Version](https://badge.fury.io/rb/sciolyff-duosmium.svg)](https://badge.fury.io/rb/sciolyff-duosmium)
4
4
 
5
5
  We propose a standardized file format called SciolyFF to represent Science
6
6
  Olympiad tournament results. This will allow for a more universal record of
@@ -9,8 +9,8 @@ other fun stuff. The format is a subset of YAML for easy implementation of
9
9
  parsers across many programming languages.
10
10
 
11
11
  A website that generates results tables based off SciolyFF files can be found
12
- [here](https://unosmium.org/results/) and the source code for the website
13
- [here](https://github.com/unosmium/unosmium.org).
12
+ [here](https://duosmium.org/results/) and the source code for the website
13
+ [here](https://github.com/Duosmium/duosmium).
14
14
 
15
15
  ## Specification
16
16
 
@@ -22,16 +22,16 @@ outlined in the comments of the demo file should be respected.
22
22
  ## Installation
23
23
 
24
24
  ```
25
- gem install sciolyff
25
+ gem install sciolyff-duosmium
26
26
  ```
27
27
 
28
28
  This gem is currently in an alpha stage. To get the latest changes before
29
29
  official releases, build from source:
30
30
 
31
31
  ```
32
- git clone https://github.com/unosmium/sciolyff.git && cd sciolyff
32
+ git clone https://github.com/Duosmium/sciolyff.git && cd sciolyff
33
33
  gem build sciolyff.gemspec
34
- gem install ./sciolyff-0.12.0.gem
34
+ gem install ./sciolyff-duosmium-0.13.1.gem
35
35
  ```
36
36
 
37
37
  ## Usage
@@ -84,9 +84,9 @@ team_one.points #=> 448
84
84
  i.teams #=> [#<...{:school=>"Troy H.S.", :number=>3, :state=>"CA"}>, ... ]
85
85
  ```
86
86
 
87
- A fuller example can be found here in the code for the Unosmium Results website,
87
+ A fuller example can be found here in the code for the Duosmium Results website,
88
88
  found
89
- [here](https://github.com/unosmium/unosmium.org/blob/master/source/results/template.html.erb).
89
+ [here](https://github.com/Duosmium/duosmium/blob/master/source/results/template.html.erb).
90
90
  There is also of course the
91
- [documentation](https://www.rubydoc.info/gems/sciolyff/0.12.0), a bit sparse
91
+ [documentation](https://www.rubydoc.info/gems/sciolyff-duosmium/0.13.1), a bit sparse
92
92
  currently.
@@ -5,7 +5,7 @@ require 'optimist'
5
5
  require 'sciolyff'
6
6
 
7
7
  opts = Optimist.options do
8
- version 'sciolyff 0.13.0'
8
+ version 'sciolyff 0.13.1'
9
9
  banner <<~STRING
10
10
  Checks if a given file is in the Scioly File Format
11
11
 
@@ -11,7 +11,7 @@ module SciolyFF
11
11
  require 'sciolyff/interpreter/penalty'
12
12
 
13
13
  require 'sciolyff/interpreter/tiebreaks'
14
- require 'sciolyff/interpreter/subdivisions'
14
+ require 'sciolyff/interpreter/tracks'
15
15
  require 'sciolyff/interpreter/html'
16
16
 
17
17
  attr_reader :tournament, :events, :teams, :placings, :penalties
@@ -29,12 +29,12 @@ module SciolyFF
29
29
  sort_teams_by_rank
30
30
  end
31
31
 
32
- def subdivisions
33
- @subdivisions ||=
34
- teams.map(&:subdivision)
32
+ def tracks
33
+ @tracks ||=
34
+ teams.map(&:track)
35
35
  .uniq
36
36
  .compact
37
- .map { |sub| [sub, Interpreter.new(subdivision_rep(sub))] }
37
+ .map { |sub| [sub, Interpreter.new(track_rep(sub))] }
38
38
  .to_h
39
39
  end
40
40
 
@@ -83,7 +83,7 @@ module SciolyFF
83
83
  end
84
84
 
85
85
  include Interpreter::Tiebreaks
86
- include Interpreter::Subdivisions
86
+ include Interpreter::Tracks
87
87
  include Interpreter::HTML
88
88
  end
89
89
  end
@@ -28,7 +28,7 @@ function(e){var t,n,r,i,o,a,s,l,u,c,f,d,p,h,m,g,v,y,b,w="sizzle"+1*new Date,x=e.
28
28
  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
29
29
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
30
30
  */
31
- e.exports=function(e){"use strict";function t(t){var r=this,i=!1;return e(this).one(n.TRANSITION_END,(function(){i=!0})),setTimeout((function(){i||n.triggerTransitionEnd(r)}),t),this}e=e&&e.hasOwnProperty("default")?e.default:e;var n={TRANSITION_END:"bsTransitionEnd",getUID:function(e){do{e+=~~(1e6*Math.random())}while(document.getElementById(e));return e},getSelectorFromElement:function(e){var t=e.getAttribute("data-target");if(!t||"#"===t){var n=e.getAttribute("href");t=n&&"#"!==n?n.trim():""}try{return document.querySelector(t)?t:null}catch(e){return null}},getTransitionDurationFromElement:function(t){if(!t)return 0;var n=e(t).css("transition-duration"),r=e(t).css("transition-delay"),i=parseFloat(n),o=parseFloat(r);return i||o?(n=n.split(",")[0],r=r.split(",")[0],1e3*(parseFloat(n)+parseFloat(r))):0},reflow:function(e){return e.offsetHeight},triggerTransitionEnd:function(t){e(t).trigger("transitionend")},supportsTransitionEnd:function(){return Boolean("transitionend")},isElement:function(e){return(e[0]||e).nodeType},typeCheckConfig:function(e,t,r){for(var i in r)if(Object.prototype.hasOwnProperty.call(r,i)){var o=r[i],a=t[i],s=a&&n.isElement(a)?"element":(l=a,{}.toString.call(l).match(/\s([a-z]+)/i)[1].toLowerCase());if(!new RegExp(o).test(s))throw new Error(e.toUpperCase()+': Option "'+i+'" provided type "'+s+'" but expected type "'+o+'".')}var l},findShadowRoot:function(e){if(!document.documentElement.attachShadow)return null;if("function"==typeof e.getRootNode){var t=e.getRootNode();return t instanceof ShadowRoot?t:null}return e instanceof ShadowRoot?e:e.parentNode?n.findShadowRoot(e.parentNode):null},jQueryDetection:function(){if(void 0===e)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var t=e.fn.jquery.split(" ")[0].split(".");if(t[0]<2&&t[1]<9||1===t[0]&&9===t[1]&&t[2]<1||t[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};return n.jQueryDetection(),e.fn.emulateTransitionEnd=t,e.event.special[n.TRANSITION_END]={bindType:"transitionend",delegateType:"transitionend",handle:function(t){if(e(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}},n}(n(0))},function(e,t,n){},function(e,t,n){(function(e){e(document).ready((function(){var t,n=e("div.results-classic-wrapper");window.onresize=function(){e(window).height()<n.height()?n.height(e(window).height()):n.css("height","")},window.onresize(),e("a.js-back-button").on("click",(function(e){e.preventDefault(),document.referrer===this.href&&window.history.length>1?window.history.back():window.location=this.href})),e("button#share-button").on("click",(function(){var n=window.location.href;if(navigator.share)navigator.share({url:n});else{let i=document.createElement("input");document.body.append(i),i.value=n,i.select(),document.execCommand("copy"),document.body.removeChild(i),window.clearTimeout(t);var r=function(){e("div#share-snack div.snackbar-body").html("Link copied! "+n),e("div#share-snack").addClass("show"),t=window.setTimeout((function(){e("div#share-snack").removeClass("show")}),2e3)};e("div#share-snack").hasClass("show")?(e("div#share-snack").removeClass("show"),window.setTimeout(r,200)):r()}})),e("div#filters input:checkbox").prop("checked",!0);var r=function(t){let n=2*e("colgroup.event-columns col").length+28+t,r=n+.5;e("div.results-classic-thead-background").css("min-width",r+"em"),e("div.results-classic-header").css("width",n+"em"),e("div.results-classic-footnotes").css("width",n+"em")};e("table.results-classic td, table.results-classic th").hover((function(){e("colgroup col").eq(e(this).index()).addClass("hover")}),(function(){e("colgroup col").eq(e(this).index()).removeClass("hover")}));var i=function(){let t=e("#sort-select option:selected").val();var n=function(t,n){return parseInt(e(t).find("td.number").text())-parseInt(e(n).find("td.number").text())};switch(t){case"number":var r=n;break;case"school":r=function(t,r){let i=e(t).find("td.team").text(),o=e(r).find("td.team").text();return i>o?1:i<o?-1:n(t,r)};break;case"rank":r=function(t,r){let i=e("#event-select option:selected").val();if("all"===i)var o=parseInt(e(t).find("td.rank").text()),a=parseInt(e(r).find("td.rank").text());else o=parseInt(e(t).find("td.event-points").eq(i).attr("data-sortable-place")),a=parseInt(e(r).find("td.event-points").eq(i).attr("data-sortable-place"));let s=o-a;return 0!==s?s:n(t,r)};break;case"state":r=function(t,r){let i=e(t).find("td.team small").text(),o=e(r).find("td.team small").text();return i>o?1:i<o?-1:n(t,r)};break;default:return}let i=e("table.results-classic tbody tr").get();i.sort(r),e.each(i,(function(t,n){e("table.results-classic tbody").append(n)}))};i(),e("#sort-select").change(i);var o=function(){let t=e("#event-select option:selected").val();if("rank"===e("#sort-select option:selected").val()&&i(),"all"!==t){e("div.results-classic-wrapper").addClass("event-focused"),e("th.event-points-focus div").text(e("#event-select option:selected").text());let n=e("table.results-classic tbody tr").get();e.each(n,(function(n,r){let i=e(r).find("td.event-points").eq(t),o=i.html(),a=i.attr("data-points"),s=e(r).find("td.event-points-focus");s.children("div").html(o),s.attr("data-points",a)})),r(4)}else e("div.results-classic-wrapper").removeClass("event-focused"),e("th.event-points-focus div").text(""),e("td.event-points-focus div").text(""),r(0)};if(o(),e("#event-select").change(o),e("th.event-points").on("click",(function(t){if(t.target!==this)return;let n=Array.prototype.indexOf.call(this.parentNode.children,this);e("#event-select").val(n-5),e("#event-select").change()})),e("th.rank, th.total-points").on("click",(function(){e("#event-select").val("all"),e("#event-select").change(),e("#sort-select").val("rank"),e("#sort-select").change()})),e("th.number").on("click",(function(){e("#sort-select").val("number"),e("#sort-select").change()})),e("th.team").on("click",(function(){e("#sort-select").val("school"),e("#sort-select").change()})),e("th.event-points-focus").on("click",(function(){e("#sort-select").val("rank"),e("#sort-select").change()})),null!==document.getElementById("subdivision")){let t=function(){let t=e("input[type=radio][name=subdivision]:checked").attr("id").substring(4),n=e("tr[data-subdivision]");"combined"===t?(n.show(),e.each(e("td.event-points"),(function(t,n){e(n).attr("data-points",e(n).attr("data-o-points")),e(n).attr("data-true-points",e(n).attr("data-o-true-points")),e(n).attr("data-notes",e(n).attr("data-o-notes")),e(n).attr("data-place",e(n).attr("data-o-place"));let r=e(n).attr("data-o-sup-tag")||"",i=e(n).attr("data-points")+r;e(n).children("div").html(i)})),e.each(e("td.rank"),(function(t,n){e(n).attr("data-points",e(n).attr("data-o-points"));let r=e(n).attr("data-o-sup-tag")||"";e(n).children("div").html(e(n).attr("data-points")+r)})),e.each(e("td.total-points"),(function(t,n){e(n).html(e(n).attr("data-o-points"))})),e("#subdivision").html("Combined")):(e.each(n,(function(n,r){e(r).attr("data-subdivision")===t?e(r).show():e(r).hide()})),e.each(e("td.event-points"),(function(t,n){e(n).attr("data-points",e(n).attr("data-sub-points")),e(n).attr("data-true-points",e(n).attr("data-sub-true-points")),e(n).attr("data-notes",e(n).attr("data-sub-notes")),e(n).attr("data-place",e(n).attr("data-sub-place"));let r=e(n).attr("data-sub-sup-tag")||"",i=e(n).attr("data-points")+r;e(n).children("div").html(i)})),e.each(e("td.rank"),(function(t,n){e(n).attr("data-points",e(n).attr("data-sub-points")),e(n).children("div").html(e(n).attr("data-sub-points"))})),e.each(e("td.total-points"),(function(t,n){e(n).html(e(n).attr("data-sub-points"))})),e("#subdivision").html(t));let r=document.querySelector("#subdivision-style"),i=document.querySelector(`#sub-${CSS.escape(t)}-style`);r.innerHTML=i.innerHTML,o()};e("input[type=radio][name=subdivision]").change(t),t()}function a(e){let t=["th","st","nd","rd"],n=parseInt(e.match(/\d+/))%100;return e+(t[(n-20)%10]||t[n]||t[0])}e("div#team-filter input").change((function(){let t=e(this).attr("id"),n=e("div#team-filter input#allTeams"),r=e("div#team-filter input").not("#allTeams");if("allTeams"===t)e(this).prop("checked")?r.not(":checked").trigger("click"):r.filter(":checked").trigger("click"),n.prop("indeterminate",!1);else{let i="table.results-classic tr[data-team-number='"+t.slice("team".length)+"']";e(this).prop("checked")?e(i).show():e(i).hide(),0===r.not(":checked").length?(n.prop("indeterminate",!1),n.prop("checked",!0)):0===r.filter(":checked").length?(n.prop("indeterminate",!1),n.prop("checked",!1)):n.prop("indeterminate",!0)}})),e("td.number a").on("click",(function(){let t=e(this).closest("tr"),n=t.children("td.total-points").text(),r=t.children("td.rank").attr("data-points");e("div#team-detail span#number").html(e(this).text()),e("div#team-detail span#points").html(n),e("div#team-detail span#place").html(a(r)),e("div#team-detail span#team").html(t.attr("data-team-name")),e("div#team-detail span#school").html(t.attr("data-school"));let i="https://unosmium.org/results/schools.html#"+t.attr("data-school").replace(/ /g,"_");window.location.href.startsWith("https://unosmium.org")&&(i=i.replace(".html","")),e("a#other-results").attr("href",i);let o=e("div#team-detail table tbody").children();e.each(t.children("td.event-points"),(function(t,n){let r=o.eq(t);r.attr("data-points",e(n).attr("data-points")),r.children().eq(1).html(e(n).attr("data-true-points"));let i=e(n).attr("data-place"),s=""===i?"n/a":a(i);r.children().eq(2).html(s),r.children().eq(3).html(e(n).attr("data-notes"))}))})),e("td.number, td.team, td.team > small").on("click",(function(t){t.target===this&&e(this).closest("tr").find("td.number a").click()})),e((function(){e('[data-toggle="popover"]').popover()}))}))}).call(this,n(0))},function(e,t,n){
31
+ e.exports=function(e){"use strict";function t(t){var r=this,i=!1;return e(this).one(n.TRANSITION_END,(function(){i=!0})),setTimeout((function(){i||n.triggerTransitionEnd(r)}),t),this}e=e&&e.hasOwnProperty("default")?e.default:e;var n={TRANSITION_END:"bsTransitionEnd",getUID:function(e){do{e+=~~(1e6*Math.random())}while(document.getElementById(e));return e},getSelectorFromElement:function(e){var t=e.getAttribute("data-target");if(!t||"#"===t){var n=e.getAttribute("href");t=n&&"#"!==n?n.trim():""}try{return document.querySelector(t)?t:null}catch(e){return null}},getTransitionDurationFromElement:function(t){if(!t)return 0;var n=e(t).css("transition-duration"),r=e(t).css("transition-delay"),i=parseFloat(n),o=parseFloat(r);return i||o?(n=n.split(",")[0],r=r.split(",")[0],1e3*(parseFloat(n)+parseFloat(r))):0},reflow:function(e){return e.offsetHeight},triggerTransitionEnd:function(t){e(t).trigger("transitionend")},supportsTransitionEnd:function(){return Boolean("transitionend")},isElement:function(e){return(e[0]||e).nodeType},typeCheckConfig:function(e,t,r){for(var i in r)if(Object.prototype.hasOwnProperty.call(r,i)){var o=r[i],a=t[i],s=a&&n.isElement(a)?"element":(l=a,{}.toString.call(l).match(/\s([a-z]+)/i)[1].toLowerCase());if(!new RegExp(o).test(s))throw new Error(e.toUpperCase()+': Option "'+i+'" provided type "'+s+'" but expected type "'+o+'".')}var l},findShadowRoot:function(e){if(!document.documentElement.attachShadow)return null;if("function"==typeof e.getRootNode){var t=e.getRootNode();return t instanceof ShadowRoot?t:null}return e instanceof ShadowRoot?e:e.parentNode?n.findShadowRoot(e.parentNode):null},jQueryDetection:function(){if(void 0===e)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var t=e.fn.jquery.split(" ")[0].split(".");if(t[0]<2&&t[1]<9||1===t[0]&&9===t[1]&&t[2]<1||t[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};return n.jQueryDetection(),e.fn.emulateTransitionEnd=t,e.event.special[n.TRANSITION_END]={bindType:"transitionend",delegateType:"transitionend",handle:function(t){if(e(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}},n}(n(0))},function(e,t,n){},function(e,t,n){(function(e){e(document).ready((function(){var t,n=e("div.results-classic-wrapper");window.onresize=function(){e(window).height()<n.height()?n.height(e(window).height()):n.css("height","")},window.onresize(),e("a.js-back-button").on("click",(function(e){e.preventDefault(),document.referrer===this.href&&window.history.length>1?window.history.back():window.location=this.href})),e("button#share-button").on("click",(function(){var n=window.location.href;if(navigator.share)navigator.share({url:n});else{let i=document.createElement("input");document.body.append(i),i.value=n,i.select(),document.execCommand("copy"),document.body.removeChild(i),window.clearTimeout(t);var r=function(){e("div#share-snack div.snackbar-body").html("Link copied! "+n),e("div#share-snack").addClass("show"),t=window.setTimeout((function(){e("div#share-snack").removeClass("show")}),2e3)};e("div#share-snack").hasClass("show")?(e("div#share-snack").removeClass("show"),window.setTimeout(r,200)):r()}})),e("div#filters input:checkbox").prop("checked",!0);var r=function(t){let n=2*e("colgroup.event-columns col").length+28+t,r=n+.5;e("div.results-classic-thead-background").css("min-width",r+"em"),e("div.results-classic-header").css("width",n+"em"),e("div.results-classic-footnotes").css("width",n+"em")};e("table.results-classic td, table.results-classic th").hover((function(){e("colgroup col").eq(e(this).index()).addClass("hover")}),(function(){e("colgroup col").eq(e(this).index()).removeClass("hover")}));var i=function(){let t=e("#sort-select option:selected").val();var n=function(t,n){return parseInt(e(t).find("td.number").text())-parseInt(e(n).find("td.number").text())};switch(t){case"number":var r=n;break;case"school":r=function(t,r){let i=e(t).find("td.team").text(),o=e(r).find("td.team").text();return i>o?1:i<o?-1:n(t,r)};break;case"rank":r=function(t,r){let i=e("#event-select option:selected").val();if("all"===i)var o=parseInt(e(t).find("td.rank").text()),a=parseInt(e(r).find("td.rank").text());else o=parseInt(e(t).find("td.event-points").eq(i).attr("data-sortable-place")),a=parseInt(e(r).find("td.event-points").eq(i).attr("data-sortable-place"));let s=o-a;return 0!==s?s:n(t,r)};break;case"state":r=function(t,r){let i=e(t).find("td.team small").text(),o=e(r).find("td.team small").text();return i>o?1:i<o?-1:n(t,r)};break;default:return}let i=e("table.results-classic tbody tr").get();i.sort(r),e.each(i,(function(t,n){e("table.results-classic tbody").append(n)}))};i(),e("#sort-select").change(i);var o=function(){let t=e("#event-select option:selected").val();if("rank"===e("#sort-select option:selected").val()&&i(),"all"!==t){e("div.results-classic-wrapper").addClass("event-focused"),e("th.event-points-focus div").text(e("#event-select option:selected").text());let n=e("table.results-classic tbody tr").get();e.each(n,(function(n,r){let i=e(r).find("td.event-points").eq(t),o=i.html(),a=i.attr("data-points"),s=e(r).find("td.event-points-focus");s.children("div").html(o),s.attr("data-points",a)})),r(4)}else e("div.results-classic-wrapper").removeClass("event-focused"),e("th.event-points-focus div").text(""),e("td.event-points-focus div").text(""),r(0)};if(o(),e("#event-select").change(o),e("th.event-points").on("click",(function(t){if(t.target!==this)return;let n=Array.prototype.indexOf.call(this.parentNode.children,this);e("#event-select").val(n-5),e("#event-select").change()})),e("th.rank, th.total-points").on("click",(function(){e("#event-select").val("all"),e("#event-select").change(),e("#sort-select").val("rank"),e("#sort-select").change()})),e("th.number").on("click",(function(){e("#sort-select").val("number"),e("#sort-select").change()})),e("th.team").on("click",(function(){e("#sort-select").val("school"),e("#sort-select").change()})),e("th.event-points-focus").on("click",(function(){e("#sort-select").val("rank"),e("#sort-select").change()})),null!==document.getElementById("track")){let t=function(){let t=e("input[type=radio][name=track]:checked").attr("id").substring(4),n=e("tr[data-track]");"combined"===t?(n.show(),e.each(e("td.event-points"),(function(t,n){e(n).attr("data-points",e(n).attr("data-o-points")),e(n).attr("data-true-points",e(n).attr("data-o-true-points")),e(n).attr("data-notes",e(n).attr("data-o-notes")),e(n).attr("data-place",e(n).attr("data-o-place"));let r=e(n).attr("data-o-sup-tag")||"",i=e(n).attr("data-points")+r;e(n).children("div").html(i)})),e.each(e("td.rank"),(function(t,n){e(n).attr("data-points",e(n).attr("data-o-points"));let r=e(n).attr("data-o-sup-tag")||"";e(n).children("div").html(e(n).attr("data-points")+r)})),e.each(e("td.total-points"),(function(t,n){e(n).html(e(n).attr("data-o-points"))})),e("#track").html("Combined")):(e.each(n,(function(n,r){e(r).attr("data-track")===t?e(r).show():e(r).hide()})),e.each(e("td.event-points"),(function(t,n){e(n).attr("data-points",e(n).attr("data-sub-points")),e(n).attr("data-true-points",e(n).attr("data-sub-true-points")),e(n).attr("data-notes",e(n).attr("data-sub-notes")),e(n).attr("data-place",e(n).attr("data-sub-place"));let r=e(n).attr("data-sub-sup-tag")||"",i=e(n).attr("data-points")+r;e(n).children("div").html(i)})),e.each(e("td.rank"),(function(t,n){e(n).attr("data-points",e(n).attr("data-sub-points")),e(n).children("div").html(e(n).attr("data-sub-points"))})),e.each(e("td.total-points"),(function(t,n){e(n).html(e(n).attr("data-sub-points"))})),e("#track").html(t));let r=document.querySelector("#track-style"),i=document.querySelector(`#sub-${CSS.escape(t)}-style`);r.innerHTML=i.innerHTML,o()};e("input[type=radio][name=track]").change(t),t()}function a(e){let t=["th","st","nd","rd"],n=parseInt(e.match(/\d+/))%100;return e+(t[(n-20)%10]||t[n]||t[0])}e("div#team-filter input").change((function(){let t=e(this).attr("id"),n=e("div#team-filter input#allTeams"),r=e("div#team-filter input").not("#allTeams");if("allTeams"===t)e(this).prop("checked")?r.not(":checked").trigger("click"):r.filter(":checked").trigger("click"),n.prop("indeterminate",!1);else{let i="table.results-classic tr[data-team-number='"+t.slice("team".length)+"']";e(this).prop("checked")?e(i).show():e(i).hide(),0===r.not(":checked").length?(n.prop("indeterminate",!1),n.prop("checked",!0)):0===r.filter(":checked").length?(n.prop("indeterminate",!1),n.prop("checked",!1)):n.prop("indeterminate",!0)}})),e("td.number a").on("click",(function(){let t=e(this).closest("tr"),n=t.children("td.total-points").text(),r=t.children("td.rank").attr("data-points");e("div#team-detail span#number").html(e(this).text()),e("div#team-detail span#points").html(n),e("div#team-detail span#place").html(a(r)),e("div#team-detail span#team").html(t.attr("data-team-name")),e("div#team-detail span#school").html(t.attr("data-school"));let i="https://unosmium.org/results/schools.html#"+t.attr("data-school").replace(/ /g,"_");window.location.href.startsWith("https://unosmium.org")&&(i=i.replace(".html","")),e("a#other-results").attr("href",i);let o=e("div#team-detail table tbody").children();e.each(t.children("td.event-points"),(function(t,n){let r=o.eq(t);r.attr("data-points",e(n).attr("data-points")),r.children().eq(1).html(e(n).attr("data-true-points"));let i=e(n).attr("data-place"),s=""===i?"n/a":a(i);r.children().eq(2).html(s),r.children().eq(3).html(e(n).attr("data-notes"))}))})),e("td.number, td.team, td.team > small").on("click",(function(t){t.target===this&&e(this).closest("tr").find("td.number a").click()})),e((function(){e('[data-toggle="popover"]').popover()}))}))}).call(this,n(0))},function(e,t,n){
32
32
  /*!
33
33
  * Bootstrap modal.js v4.4.1 (https://getbootstrap.com/)
34
34
  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
@@ -1,20 +1,15 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta http-equiv="x-ua-compatible" content="ie=edge">
6
- <meta name="viewport"
7
- content="width=device-width, initial-scale=1, shrink-to-fit=no">
8
- <title><%=
9
- "#{i.tournament.year} "\
1
+ ---
2
+ custom_colors: true
3
+ ---
4
+ <% current_page.data.title =
5
+ "#{i.tournament.year} "\
10
6
  "#{tournament_title_short(i.tournament)} " \
11
- "(Div. #{i.tournament.division}) | Unosmium Results"
12
- %></title>
13
- <% if i.tournament.teams.count > 1 %>
7
+ "(Div. #{i.tournament.division}) | Duosmium Results" %>
8
+
14
9
  <% champion = i.tournament.teams[0] %>
15
10
  <% runnerup = i.tournament.teams[1] %>
16
- <meta name="Description" content="<%=
17
- "Full results for the #{i.tournament.year} "\
11
+ <% current_page.data.description =
12
+ "Full results for the #{i.tournament.year} "\
18
13
  "#{tournament_title(i.tournament)} "\
19
14
  "(Division #{i.tournament.division}), "\
20
15
  "Champion: #{champion.school} "\
@@ -24,232 +19,217 @@
24
19
  "#{runnerup.suffix ? runnerup.suffix + " " : ""}"\
25
20
  "(#{runnerup.points} pts), "\
26
21
  "Total non-exhibition teams: #{i.tournament.nonexhibition_teams_count}" %>
27
- %>">
28
- <% end %>
29
- <link href="data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAQAAAD9CzEMAAACDElEQVR4Ae3VA8wcURhG4VPbtm03qK3oj1lEbVTbtm3bbsPatm3bfeve7M3Ozt2t8Zx4zI/fVUV+sBU05ofqgOjFD1QVITrxwyRHH2vED3MDId5Qjx9kE/rYXVLxQ8xHn1vLDzESfa0hEYlBCbz1R1+7SyIiMIIWeBuKMA0lbNUQw32egek1OQlLQi4jDuLtGgpoFmHpij5WmuAqIKtXpMFZQu6jj+0lHmCLxW6EXS+ctUJfW499iOjMQkG6TQycROMiMrGb/BipWYk8Ko+T6sjqLWdZTn9mso/XyLMBOJmEIuw4DmLwEDm3BAWUEV8lkHNriM4tZKIevpohxyYQD1iMTHTC11Tk0EmqAgCtkYlFroPEuwfMprL1zzLtxNeFEGfdlwrEJFBxax1f91GQDlGY4LIiEzfx9RbZsZ74eElsfZK+HgX5xyTFWzSE6RG+TiGrJoSSCmE6ha+NyKoIoZREmDbiayyyik0oXRCmcfiqjazi4y0W5xCm2viKzRMUUCW8dUCYnhIbB+NRQDPxUtaaDhNwkoZnKKCaBFOAGwjTM1LjqD8K6B4VCBSTBthzoz/O4nEAe2guogGFiQGkph2XkdUe4oG7tFxCuHeZlIQpN2eQY+fIRQSSsR05tJNkRCg2HXiKQvSUDsTmm6RhgsdBnjKBNHwX8YhiHnu5yHOecYl9zCGKuPwR/nsHqpaOEAqfQCAAAAAASUVORK5CYII=" rel="icon" type="image/png" />
30
- <style>
31
- .results-classic-thead-background {
32
- background-color: <%= color %> !important;
33
- }
34
- .btn, .custom-control-label::after {
35
- color: <%= color %> !important;
36
- }
37
- <%= css_file_content %>
38
- <% if i.tournament.subdivisions? %>
39
- </style>
40
- <style id="subdivision-style">
41
- <% end %>
42
- <%= trophy_and_medal_css(i.tournament.trophies, i.tournament.medals) %>
43
- </style>
44
- </head>
45
- <body>
46
22
 
47
23
  <div class="results-classic-wrapper">
48
- <div class="results-classic-thead-background shadow-sm"
49
- style="min-width: <%= 2*(i.events.count + 1) + 28.5 %>em;">
50
- <div class="results-classic-header"
51
- style="width: <%= 2*(i.events.count + 1) + 28 %>em">
52
- <div class="tournament-info">
53
- <h1>
54
- <%= i.tournament.year %>
55
- <%= tournament_title(i.tournament) %>&nbsp;(Div. <%= i.tournament.division %><%= ' <span id="subdivision">Combined</span>' if i.tournament.subdivisions? %>)
56
- </h1>
57
- <p><%= i.tournament.date.strftime('%A, %B %-d, %Y') %>
58
- @ <span style="white-space: nowrap;"><%= i.tournament.location %></span></p>
59
- </div>
60
- <div class="actions">
61
- <a href="https://unosmium.org/results/" class="js-back-button">
62
- <svg viewBox="0 0 24 24"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg>
63
- </a>
64
- <button type="button" data-toggle="modal" data-target="#download-info">
65
- <svg viewBox="0 0 24 24"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/></svg>
66
- </button>
67
- <button type="button" data-toggle="modal" data-target="#print-instructions">
68
- <svg viewBox="0 0 24 24"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"/></svg>
69
- </button>
70
- <button type="button" id="share-button">
71
- <svg viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z"/></svg>
72
- </button>
73
- <select id="event-select" class="custom-select custom-select-sm"
74
- aria-label="Select Event Filter">
75
- <option value="all" selected>All Events</option>
76
- <% i.events.each.with_index do |e, i| %>
77
- <option value="<%= i %>">
78
- <%= e.name %>
79
- <% if e.trial? %>
80
- (Trial)
81
- <% elsif e.trialed? %>
82
- (Trialed)
24
+ <div class="results-classic-thead-background shadow-sm"
25
+ style="min-width: <%= 2*(i.events.count + 1) + 28.5 %>em;">
26
+ <div class="results-classic-header"
27
+ style="width: <%= 2*(i.events.count + 1) + 28 %>em">
28
+ <div class="tournament-info">
29
+ <h1>
30
+ <%= i.tournament.year %>
31
+ <%= tournament_title(i.tournament) %>&nbsp;(Div. <%= i.tournament.division %><%= ' <span id="track">Combined</span>' if i.tournament.tracks? %>)
32
+ </h1>
33
+ <% if i.tournament.start_date.strftime('%A, %B %-d, %Y') == i.tournament.end_date.strftime('%A, %B %-d, %Y')%>
34
+ <p><%= i.tournament.date.strftime('%A, %B %-d, %Y') %></p>
35
+ <% else %>
36
+ <p><%= i.tournament.start_date.strftime('%A, %B %-d, %Y') %> - <%= i.tournament.end_date.strftime('%A, %B %-d, %Y') %></p>
37
+ <% end %>
38
+ <p>@ <span style="white-space: nowrap;"><%= i.tournament.location %></span></p>
39
+ </div>
40
+ <div class="actions">
41
+ <a href="../results/index.html" class="js-back-button">
42
+ <svg viewBox="0 0 24 24"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg>
43
+ </a>
44
+ <button type="button" data-toggle="modal" data-target="#download-info">
45
+ <svg viewBox="0 0 24 24"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/></svg>
46
+ </button>
47
+ <button type="button" data-toggle="modal" data-target="#print-instructions">
48
+ <svg viewBox="0 0 24 24"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"/></svg>
49
+ </button>
50
+ <button type="button" id="share-button">
51
+ <svg viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z"/></svg>
52
+ </button>
53
+ <select id="event-select" class="custom-select custom-select-sm"
54
+ aria-label="Select Event Filter">
55
+ <option value="all" selected>All Events</option>
56
+ <% i.events.each.with_index do |e, i| %>
57
+ <option value="<%= i %>">
58
+ <%= e.name %>
59
+ <% if e.trial? %>
60
+ (Trial)
61
+ <% elsif e.trialed? %>
62
+ (Trialed)
63
+ <% end %>
64
+ </option>
83
65
  <% end %>
84
- </option>
85
- <% end %>
86
- </select>
87
- <select id="sort-select" class="custom-select custom-select-sm"
88
- aria-label="Select Sort Method">
89
- <option value="number">by Number</option>
90
- <option value="school">by School</option>
91
- <option value="state">by State</option>
92
- <option value="rank" selected>by Rank</option>
93
- </select>
94
- <button type="button" data-toggle="modal" data-target="#filters" class="settings">
95
- <svg viewBox="0 0 24 24"><path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/></svg>
96
- </button>
66
+ </select>
67
+ <select id="sort-select" class="custom-select custom-select-sm"
68
+ aria-label="Select Sort Method">
69
+ <option value="number">by Number</option>
70
+ <option value="school">by School</option>
71
+ <option value="state">by State</option>
72
+ <option value="rank" selected>by Rank</option>
73
+ </select>
74
+ <button type="button" data-toggle="modal" data-target="#filters" class="settings">
75
+ <svg viewBox="0 0 24 24"><path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/></svg>
76
+ </button>
77
+ </div>
78
+ <p class="source">
79
+ Source:
80
+ <a href="https://duosmium.org<%= current_page.url %>">
81
+ Duosmium Results
82
+ </a>
83
+ </p>
97
84
  </div>
98
- <p class="source">
99
- Generated using
100
- <a href="https://github.com/unosmium/sciolyff">
101
- SciolyFF
102
- </a>
103
- </p>
104
85
  </div>
105
- </div>
106
- <table class="results-classic table-hover">
107
- <colgroup>
108
- <col>
109
- <col>
110
- <col>
111
- <col>
112
- <col>
113
- </colgroup>
114
- <colgroup class="event-columns">
115
- <% i.events.count.times do %>
116
- <col>
117
- <% end %>
118
- <col> <%# for team penalties, which kinda act like an additional event %>
119
- </colgroup>
120
- <thead>
121
- <tr>
122
- <th class="number">#</th>
123
- <th class="team">Team</th>
124
- <th class="event-points-focus"><div></div></th>
125
- <th class="rank"><div>Overall</div></th>
126
- <th class="total-points">Total</th>
127
- <% i.events.each do |e| %>
128
- <th class="event-points">
129
- <%= e.name %>
130
- <% if e.trial? %>
131
- <a tabindex="0" role="button"
132
- data-toggle="popover" data-trigger="focus"
133
- title="Trial Event"
134
- data-content="Placings in this event did not count towards total
86
+ <table class="results-classic table-hover">
87
+ <colgroup>
88
+ <col>
89
+ <col>
90
+ <col>
91
+ <col>
92
+ <col>
93
+ </colgroup>
94
+ <colgroup class="event-columns">
95
+ <% i.events.count.times do %>
96
+ <col>
97
+ <% end %>
98
+ <col> <%# for team penalties, which kinda act like an additional event %>
99
+ </colgroup>
100
+ <thead>
101
+ <tr>
102
+ <th class="number">#</th>
103
+ <th class="team">Team</th>
104
+ <th class="event-points-focus"><div></div></th>
105
+ <th class="rank"><div>Overall</div></th>
106
+ <th class="total-points">Total</th>
107
+ <% i.events.each do |e| %>
108
+ <th class="event-points">
109
+ <%= e.name %>
110
+ <% if e.trial? %>
111
+ <a tabindex="0" role="button"
112
+ data-toggle="popover" data-trigger="focus"
113
+ title="Trial Event"
114
+ data-content="Placings in this event did not count towards total
135
115
  team score">
136
- <span class="badge badge-info"><small>T</small></span>
137
- </a>
138
- <% elsif e.trialed? %>
139
- <a tabindex="0" role="button"
140
- data-toggle="popover" data-trigger="focus"
141
- title="Trialed Event"
142
- data-content="Placings in this event did not count towards total
116
+ <span class="badge badge-info"><small>T</small></span>
117
+ </a>
118
+ <% elsif e.trialed? %>
119
+ <a tabindex="0" role="button"
120
+ data-toggle="popover" data-trigger="focus"
121
+ title="Trialed Event"
122
+ data-content="Placings in this event did not count towards total
143
123
  team score because of unforseen circumstances during
144
124
  the competition">
145
- <span class="badge badge-danger"><small>Td</small></span>
146
- </a>
147
- <% end %>
148
- </th>
149
- <% end %>
150
- <th class="team-penalties">Team Penalties</th>
151
- </tr>
152
- </thead>
153
- <tbody>
154
- <% i.teams.each do |tm| %>
155
- <tr data-team-number="<%= tm.number %>"
156
- data-school="<%= full_school_name(tm) %>"
157
- data-team-name="<%= full_team_name(tm) %>"<%= " data-subdivision=\"#{tm.subdivision}\"" if i.tournament.subdivisions? %>>
158
- <td class="number">
159
- <a href="?team=<%= tm.number %>"
160
- data-toggle="modal" data-target="#team-detail">
161
- <%= tm.number %>
162
- </a>
163
- </td>
164
- <td class="team">
165
- <%= format_school(tm) %>
166
- <%= tm.suffix %>
167
- <%= "(#{tm.city})" if tm.city %>
168
- <small><%= tm.state %></small>
169
- <% if tm.disqualified? %>
170
- <a tabindex="0" role="button"
171
- data-toggle="popover" data-trigger="focus"
172
- title="Disqualified Team"
173
- data-content="This team is ranked behind all other teams that were not
125
+ <span class="badge badge-danger"><small>Td</small></span>
126
+ </a>
127
+ <% end %>
128
+ </th>
129
+ <% end %>
130
+ <th class="team-penalties">Team Penalties</th>
131
+ </tr>
132
+ </thead>
133
+ <tbody>
134
+ <% i.teams.each do |tm| %>
135
+ <tr data-team-number="<%= tm.number %>"
136
+ data-school="<%= full_school_name(tm) %>"
137
+ data-team-name="<%= full_team_name(tm) %>"<%= " data-track=\"#{tm.track}\"" if i.tournament.tracks? %>>
138
+ <td class="number">
139
+ <a href="?team=<%= tm.number %>"
140
+ data-toggle="modal" data-target="#team-detail">
141
+ <%= tm.number %>
142
+ </a>
143
+ </td>
144
+ <td class="team">
145
+ <%= format_school(tm) %>
146
+ <%= tm.suffix %>
147
+ <%= "(#{tm.city})" if tm.city %>
148
+ <small><%= tm.state %></small>
149
+ <% if tm.disqualified? %>
150
+ <a tabindex="0" role="button"
151
+ data-toggle="popover" data-trigger="focus"
152
+ title="Disqualified Team"
153
+ data-content="This team is ranked behind all other teams that were not
174
154
  disqualified">
175
- <span class="badge badge-danger"><small>Dq</small></span>
176
- <% elsif tm.exhibition? %>
177
- <a tabindex="0" role="button"
178
- data-toggle="popover" data-trigger="focus"
179
- <% if team_attended?(tm) %>
180
- title="Exhibition Team"
181
- data-content="Placings by this team did not affect the ranks of other
155
+ <span class="badge badge-danger"><small>Dq</small></span>
156
+ <% elsif tm.exhibition? %>
157
+ <a tabindex="0" role="button"
158
+ data-toggle="popover" data-trigger="focus"
159
+ <% if team_attended?(tm) %>
160
+ title="Exhibition Team"
161
+ data-content="Placings by this team did not affect the ranks of other
182
162
  teams (except in Trial Events)">
183
- <span class="badge badge-warning"><small>Ex</small></span>
184
- <% else %>
185
- title="Absent Team"
186
- data-content="This team registered but did not compete, and so was
187
- treated as an Exhibition Team">
188
- <span class="badge badge-light"><small>Ab</small></span>
189
- <% end %>
190
- </a>
163
+ <span class="badge badge-warning"><small>Ex</small></span>
164
+ <% else %>
165
+ title="Absent Team"
166
+ data-content="This team registered but did not compete, and so was
167
+ treated as an Exhibition Team">
168
+ <span class="badge badge-light"><small>Ab</small></span>
169
+ <% end %>
170
+ </a>
171
+ <% end %>
172
+ </td>
173
+ <td class="event-points-focus" data-points=""><div></div></td>
174
+ <td class="rank" data-points="<%= tm.rank %>"<%= " data-o-points=\"#{tm.rank}\" data-o-sup-tag=\"#{bids_sup_tag(tm)}\" data-sub-points=\"#{tm.track_team.rank}\"" if tm.track %>><div><%= tm.rank %><%= bids_sup_tag(tm) %></div></td>
175
+ <td class="total-points"<%= " data-o-points=\"#{tm.points}\" data-sub-points=\"#{tm.track_team.points}\"" if tm.track %>><%= tm.points %></td>
176
+ <% i.events.each do |e| %>
177
+ <% placing = e.placing_for(tm) %>
178
+ <% points = placing.isolated_points %>
179
+ <% place = placing.place %>
180
+ <% unknown = placing.unknown? %>
181
+ <td class="event-points"
182
+ data-true-points="<%= placing.points %>"
183
+ data-notes="<%= placing_notes(placing) %>"
184
+ data-points="<%= unknown ? '??' : points %>"
185
+ data-place="<%= unknown && placing.points_limited_by_maximum_place? ? "≥#{i.tournament.maximum_place}" : place %>"
186
+ <% if tm.track %>
187
+ data-o-true-points="<%= placing.points %>"
188
+ data-o-notes="<%= placing_notes(placing) %>"
189
+ data-o-points="<%= unknown ? '??' : points %>"
190
+ data-o-place="<%= unknown && placing.points_limited_by_maximum_place? ? "≥#{i.tournament.maximum_place}" : place %>"
191
+ data-o-sup-tag="<%= sup_tag(placing) %>"
192
+ <% sp = placing.track_placing %>
193
+ data-sub-true-points="<%= sp.points %>"
194
+ data-sub-notes="<%= placing_notes(sp) %>"
195
+ data-sub-points="<%= sp.unknown? ? '??' : sp.isolated_points %>"
196
+ data-sub-place="<%= sp.place %>"
197
+ data-sub-sup-tag="<%= sup_tag(sp) %>"
198
+ <% end %>
199
+ data-sortable-place="<%= place ? place : (unknown ? 998000 + points : 999000 + points) %>">
200
+ <div><%= unknown && !placing.points_limited_by_maximum_place? ? '??' : points %><%= sup_tag(placing) %></div>
201
+ </td>
202
+ <% end %>
203
+ <% pen_points = tm.penalties.sum(&:points) %>
204
+ <td class="team-penalties text-muted" data-points="<%= pen_points %>">
205
+ <%= pen_points.zero? ? "00" : "+#{pen_points}" %>
206
+ </td>
207
+ </tr>
208
+ <% end %>
209
+ </tbody>
210
+ </table>
211
+ <div class="results-classic-footnotes"
212
+ style="width: <%= 2*(i.events.count + 1) + 28 %>em">
213
+ <% if i.tournament.ties? || i.tournament.exempt_placings? || i.tournament.worst_placings_dropped? || i.tournament.bids.nonzero? %>
214
+ <div class="wrapper">
215
+ <% if i.tournament.bids.nonzero? %>
216
+ <p class="footnote">
217
+ <sup>✧</sup><%= bids_sup_tag_note(i.tournament) %>
218
+ </p>
219
+ <% end %>
220
+ <% if i.tournament.exempt_placings? || i.tournament.worst_placings_dropped? %>
221
+ <p class="footnote">
222
+ <sup>◊</sup>Result was not counted as part of total score
223
+ </p>
224
+ <% end %>
225
+ <% if i.tournament.ties_outside_of_maximum_places? %>
226
+ <p class="footnote">
227
+ <sup>*</sup>Tied with another team
228
+ </p>
229
+ <% end %>
230
+ </div>
191
231
  <% end %>
192
- </td>
193
- <td class="event-points-focus" data-points=""><div></div></td>
194
- <td class="rank" data-points="<%= tm.rank %>"<%= " data-o-points=\"#{tm.rank}\" data-o-sup-tag=\"#{bids_sup_tag(tm)}\" data-sub-points=\"#{tm.subdivision_team.rank}\"" if tm.subdivision %>><div><%= tm.rank %><%= bids_sup_tag(tm) %></div></td>
195
- <td class="total-points"<%= " data-o-points=\"#{tm.points}\" data-sub-points=\"#{tm.subdivision_team.points}\"" if tm.subdivision %>><%= tm.points %></td>
196
- <% i.events.each do |e| %>
197
- <% placing = e.placing_for(tm) %>
198
- <% points = placing.isolated_points %>
199
- <% place = placing.place %>
200
- <% unknown = placing.unknown? %>
201
- <td class="event-points"
202
- data-true-points="<%= placing.points %>"
203
- data-notes="<%= placing_notes(placing) %>"
204
- data-points="<%= unknown ? '??' : points %>"
205
- data-place="<%= unknown && placing.points_limited_by_maximum_place? ? "≥#{i.tournament.maximum_place}" : place %>"
206
- <% if tm.subdivision %>
207
- data-o-true-points="<%= placing.points %>"
208
- data-o-notes="<%= placing_notes(placing) %>"
209
- data-o-points="<%= unknown ? '??' : points %>"
210
- data-o-place="<%= unknown && placing.points_limited_by_maximum_place? ? "≥#{i.tournament.maximum_place}" : place %>"
211
- data-o-sup-tag="<%= sup_tag(placing) %>"
212
- <% sp = placing.subdivision_placing %>
213
- data-sub-true-points="<%= sp.points %>"
214
- data-sub-notes="<%= placing_notes(sp) %>"
215
- data-sub-points="<%= sp.unknown? ? '??' : sp.isolated_points %>"
216
- data-sub-place="<%= sp.place %>"
217
- data-sub-sup-tag="<%= sup_tag(sp) %>"
218
- <% end %>
219
- data-sortable-place="<%= place ? place : (unknown ? 998000 + points : 999000 + points) %>">
220
- <div><%= unknown && !placing.points_limited_by_maximum_place? ? '??' : points %><%= sup_tag(placing) %></div>
221
- </td>
222
- <% end %>
223
- <% pen_points = tm.penalties.sum(&:points) %>
224
- <td class="team-penalties text-muted" data-points="<%= pen_points %>">
225
- <%= pen_points.zero? ? "00" : "+#{pen_points}" %>
226
- </td>
227
- </tr>
228
- <% end %>
229
- </tbody>
230
- </table>
231
- <div class="results-classic-footnotes"
232
- style="width: <%= 2*(i.events.count + 1) + 28 %>em">
233
- <% if i.tournament.ties? || i.tournament.exempt_placings? || i.tournament.worst_placings_dropped? || i.tournament.bids.nonzero? %>
234
- <div class="wrapper">
235
- <% if i.tournament.bids.nonzero? %>
236
- <p class="footnote">
237
- <sup>✧</sup><%= bids_sup_tag_note(i.tournament) %>
238
- </p>
239
- <% end %>
240
- <% if i.tournament.exempt_placings? || i.tournament.worst_placings_dropped? %>
241
- <p class="footnote">
242
- <sup>◊</sup>Result was not counted as part of total score
243
- </p>
244
- <% end %>
245
- <% if i.tournament.ties_outside_of_maximum_places? %>
246
- <p class="footnote">
247
- <sup>*</sup>Tied with another team
248
- </p>
249
- <% end %>
250
232
  </div>
251
- <% end %>
252
- </div>
253
233
  </div>
254
234
  <div class="modal" id="filters" tabindex="-1" role="dialog"
255
235
  aria-labelledby="filters-label" aria-hidden="true">
@@ -265,24 +245,24 @@
265
245
  </button>
266
246
  </div>
267
247
  <div class="modal-body">
268
- <% if i.tournament.subdivisions? %>
269
- <h6>Select which subdivision to show</h6>
270
- <div>
271
- <input type="radio" id="sub-combined" name="subdivision" checked>
272
- <label class="custom-control-label" for="sub-combined">
273
- Combined (all teams)
274
- </label>
275
- </div>
276
- <% i.tournament.subdivisions.each do |s, _| %>
277
- <div>
278
- <input type="radio" id="sub-<%= s %>" name="subdivision">
279
- <label class="custom-control-label" for="sub-<%= s %>">
280
- <%= s %>
281
- </label>
282
- </div>
283
- <% end %>
284
- <hr>
285
- <% end %>
248
+ <% if i.tournament.tracks? %>
249
+ <h6>Select which track to show</h6>
250
+ <div>
251
+ <input type="radio" id="sub-combined" name="track" checked>
252
+ <label class="custom-control-label" for="sub-combined">
253
+ Combined (all teams)
254
+ </label>
255
+ </div>
256
+ <% i.tournament.tracks.each do |s, _| %>
257
+ <div>
258
+ <input type="radio" id="sub-<%= s %>" name="track">
259
+ <label class="custom-control-label" for="sub-<%= s %>">
260
+ <%= s %>
261
+ </label>
262
+ </div>
263
+ <% end %>
264
+ <hr>
265
+ <% end %>
286
266
  <h6>Select which teams to show</h6>
287
267
  <div id="team-filter">
288
268
  <div>
@@ -292,18 +272,18 @@
292
272
  All Teams
293
273
  </label>
294
274
  </div>
295
- <% i.teams.sort_by(&:number).each do |tm| %>
296
- <div>
297
- <input type="checkbox"
298
- id="team<%= tm.number %>" checked>
299
- <label class="custom-control-label" for="team<%= tm.number %>">
300
- <%= tm.number %> <%= format_school(tm) %>
301
- <%= tm.suffix %>
302
- <%= "(#{tm.city})" if tm.city %>
303
- <small><%= tm.state %></small>
304
- </label>
305
- </div>
306
- <% end %>
275
+ <% i.teams.sort_by(&:number).each do |tm| %>
276
+ <div>
277
+ <input type="checkbox"
278
+ id="team<%= tm.number %>" checked>
279
+ <label class="custom-control-label" for="team<%= tm.number %>">
280
+ <%= tm.number %> <%= format_school(tm) %>
281
+ <%= tm.suffix %>
282
+ <%= "(#{tm.city})" if tm.city %>
283
+ <small><%= tm.state %></small>
284
+ </label>
285
+ </div>
286
+ <% end %>
307
287
  </div>
308
288
  </div>
309
289
  <div class="modal-footer">
@@ -375,10 +355,10 @@
375
355
  ) instead.
376
356
  </p>
377
357
  <p>
378
- The results will be downloaded as a stand-alone HTML file that can be
379
- opened in your browser for offline viewing. Note: the SciolyFF YAML is
380
- embedded at the end of the file. For more info about SciolyFF, see its
381
- <a href="https://github.com/unosmium/sciolyff">GitHub repository</a>.
358
+ The results will be downloaded as a YAML file, specifically in the
359
+ SciolyFF, and can be opened with any text editor or parsed with your
360
+ favorite programming language. For more info about SciolyFF, see its
361
+ <a href="https://github.com/smayya337/sciolyff">GitHub repository</a>.
382
362
  </p>
383
363
  <p>
384
364
  If you really want a CSV file, select CANCEL, copy the whole table
@@ -392,7 +372,7 @@
392
372
  Cancel
393
373
  </button>
394
374
  <a role="button" class="btn btn-secondary"
395
- href="#" download>
375
+ href="../data/<%= File.basename(current_page.path, '.html') + '.yaml' %>">
396
376
  Download
397
377
  </a>
398
378
  </div>
@@ -415,31 +395,31 @@
415
395
  <div class="modal-body">
416
396
  <h6>Summary</h6>
417
397
  <p><span id="team">[team]</span> placed <span id="place">[place]</span>
418
- overall with a total score of <span id="points">[points]</span> points.
398
+ overall with a total score of <span id="points">[points]</span> points.
419
399
  <hr>
420
400
  <div class="table-responsive-md">
421
- <table class="table-striped">
422
- <thead>
423
- <tr>
424
- <th class="event">Event</th>
425
- <th class="points">Points</th>
426
- <th class="place">Place</th>
427
- <th class="notes">Notes</th>
428
- </tr>
429
- </thead>
430
- <tbody>
431
- <% i.events.each do |e| %>
432
- <tr>
433
- <td class="event">
434
- <%= e.name %>
435
- </td>
436
- <td class="points"></td>
437
- <td class="place"></td>
438
- <td class="notes"></td>
439
- </tr>
440
- <% end %>
441
- </tbody>
442
- </table>
401
+ <table class="table-striped">
402
+ <thead>
403
+ <tr>
404
+ <th class="event">Event</th>
405
+ <th class="points">Points</th>
406
+ <th class="place">Place</th>
407
+ <th class="notes">Notes</th>
408
+ </tr>
409
+ </thead>
410
+ <tbody>
411
+ <% i.events.each do |e| %>
412
+ <tr>
413
+ <td class="event">
414
+ <%= e.name %>
415
+ </td>
416
+ <td class="points"></td>
417
+ <td class="place"></td>
418
+ <td class="notes"></td>
419
+ </tr>
420
+ <% end %>
421
+ </tbody>
422
+ </table>
443
423
  </div>
444
424
  <hr>
445
425
  <h6>Other Results</h6>
@@ -460,21 +440,3 @@
460
440
  <%# populated using JS %>
461
441
  </div>
462
442
  </div>
463
- <script>
464
- <%= js_file_content %>
465
- </script>
466
- <% if i.tournament.subdivisions? %>
467
- <x-st id="sub-combined-style">
468
- <%= trophy_and_medal_css(i.tournament.trophies, i.tournament.medals) %>
469
- </x-st>
470
- <% i.subdivisions.each do |sub, sub_i| %>
471
- <x-st id="sub-<%= sub %>-style">
472
- <%= trophy_and_medal_css(sub_i.tournament.trophies, sub_i.tournament.medals) %>
473
- </x-st>
474
- <% end %>
475
- <% end %>
476
- <sciolyff-yaml hidden>
477
- <%= i.to_yaml(hide_raw: hide_raw) %>
478
- </sciolyff-yaml>
479
- </body>
480
- </html>
@@ -12,10 +12,10 @@ module SciolyFF
12
12
  @event = interpreter.events.find { |e| e.name == @rep[:event] }
13
13
  @team = interpreter.teams .find { |t| t.number == @rep[:team] }
14
14
 
15
- link_to_placing_in_subdivision_interpreter(interpreter)
15
+ link_to_placing_in_track_interpreter(interpreter)
16
16
  end
17
17
 
18
- attr_reader :event, :team, :subdivision_placing
18
+ attr_reader :event, :team, :track_placing
19
19
 
20
20
  def participated?
21
21
  @rep[:participated] || @rep[:participated].nil?
@@ -116,10 +116,10 @@ module SciolyFF
116
116
  end
117
117
  end
118
118
 
119
- def link_to_placing_in_subdivision_interpreter(interpreter)
120
- return @subdivision_placing = nil unless (sub = team.subdivision)
119
+ def link_to_placing_in_track_interpreter(interpreter)
120
+ return @track_placing = nil unless (sub = team.track)
121
121
 
122
- @subdivision_placing = interpreter.subdivisions[sub].placings.find do |p|
122
+ @track_placing = interpreter.tracks[sub].placings.find do |p|
123
123
  p.event.name == event.name && p.team.number == team.number
124
124
  end
125
125
  end
@@ -12,10 +12,10 @@ module SciolyFF
12
12
  @placings_by_event =
13
13
  @placings.group_by(&:event).transform_values!(&:first)
14
14
 
15
- link_to_team_in_subdivision_interpreter(interpreter)
15
+ link_to_team_in_track_interpreter(interpreter)
16
16
  end
17
17
 
18
- attr_reader :placings, :penalties, :subdivision_team
18
+ attr_reader :placings, :penalties, :track_team
19
19
 
20
20
  def school
21
21
  @rep[:school]
@@ -29,8 +29,8 @@ module SciolyFF
29
29
  @rep[:suffix]
30
30
  end
31
31
 
32
- def subdivision
33
- @rep[:subdivision]
32
+ def track
33
+ @rep[:track]
34
34
  end
35
35
 
36
36
  def exhibition?
@@ -100,10 +100,10 @@ module SciolyFF
100
100
 
101
101
  private
102
102
 
103
- def link_to_team_in_subdivision_interpreter(interpreter)
104
- return @subdivision_team = nil unless (sub = subdivision)
103
+ def link_to_team_in_track_interpreter(interpreter)
104
+ return @track_team = nil unless (sub = track)
105
105
 
106
- @subdivision_team = interpreter.subdivisions[sub].teams.find do |t|
106
+ @track_team = interpreter.tracks[sub].teams.find do |t|
107
107
  t.number == number
108
108
  end
109
109
  end
@@ -15,10 +15,10 @@ module SciolyFF
15
15
  @teams = interpreter.teams
16
16
  @placings = interpreter.placings
17
17
  @penalties = interpreter.penalties
18
- @subdivisions = interpreter.subdivisions
18
+ @tracks = interpreter.tracks
19
19
  end
20
20
 
21
- attr_reader :events, :teams, :placings, :penalties, :subdivisions
21
+ attr_reader :events, :teams, :placings, :penalties, :tracks
22
22
 
23
23
  undef tournament
24
24
 
@@ -171,8 +171,8 @@ module SciolyFF
171
171
  end
172
172
  end
173
173
 
174
- def subdivisions?
175
- !@subdivisions.empty?
174
+ def tracks?
175
+ !@tracks.empty?
176
176
  end
177
177
 
178
178
  def nonexhibition_teams_count
@@ -1,37 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SciolyFF
4
- # Subdivision logic, to be used in the Interpreter class
5
- module Interpreter::Subdivisions
4
+ # Track logic, to be used in the Interpreter class
5
+ module Interpreter::Tracks
6
6
  private
7
7
 
8
- def subdivision_rep(sub)
8
+ def track_rep(sub)
9
9
  # make a deep copy of rep
10
10
  rep = Marshal.load(Marshal.dump(@rep))
11
11
 
12
- remove_teams_not_in_subdivision(rep, sub)
13
- fix_subdivision_tournament_fields(rep, sub)
12
+ remove_teams_not_in_track(rep, sub)
13
+ fix_track_tournament_fields(rep, sub)
14
14
  limit_maximum_place(rep)
15
15
  fix_placings_for_existing_teams(rep) unless raws?
16
16
  rep
17
17
  end
18
18
 
19
- def remove_teams_not_in_subdivision(rep, sub)
20
- rep[:Teams].select! { |t| t.delete(:subdivision) == sub }
19
+ def remove_teams_not_in_track(rep, sub)
20
+ rep[:Teams].select! { |t| t.delete(:track) == sub }
21
21
 
22
22
  team_numbers = rep[:Teams].map { |t| t[:number] }
23
23
  rep[:Placings].select! { |p| team_numbers.include? p[:team] }
24
24
  end
25
25
 
26
- def fix_subdivision_tournament_fields(rep, sub)
26
+ def fix_track_tournament_fields(rep, sub)
27
27
  tournament_rep = rep[:Tournament]
28
- sub_rep = rep[:Subdivisions].find { |s| s[:name] == sub }
28
+ sub_rep = rep[:Tracks].find { |s| s[:name] == sub }
29
29
 
30
30
  replace_tournament_fields(tournament_rep, sub_rep)
31
31
 
32
32
  tournament_rep.delete(:bids)
33
33
  tournament_rep.delete(:'bids per school')
34
- rep.delete(:Subdivisions)
34
+ rep.delete(:Tracks)
35
35
  end
36
36
 
37
37
  def replace_tournament_fields(tournament_rep, sub_rep)
@@ -10,7 +10,7 @@ module SciolyFF
10
10
 
11
11
  require 'sciolyff/validator/top_level'
12
12
  require 'sciolyff/validator/tournament'
13
- require 'sciolyff/validator/subdivisions'
13
+ require 'sciolyff/validator/tracks'
14
14
  require 'sciolyff/validator/events'
15
15
  require 'sciolyff/validator/teams'
16
16
  require 'sciolyff/validator/placings'
@@ -65,7 +65,7 @@ module SciolyFF
65
65
  def check_all(rep, logger)
66
66
  check(TopLevel, rep, rep, logger) &&
67
67
  check(Tournament, rep, rep[:Tournament], logger) &&
68
- [Subdivisions, Events, Teams, Placings, Penalties].all? do |klass|
68
+ [Tracks, Events, Teams, Placings, Penalties].all? do |klass|
69
69
  check_list(klass, rep, logger)
70
70
  end &&
71
71
  rep[:Placings].map { |p| p[:raw] }.compact.all? do |r|
@@ -17,7 +17,7 @@ module SciolyFF
17
17
 
18
18
  OPTIONAL = {
19
19
  'school abbreviation': String,
20
- subdivision: String,
20
+ track: String,
21
21
  suffix: String,
22
22
  city: String,
23
23
  disqualified: [true, false],
@@ -26,7 +26,7 @@ module SciolyFF
26
26
 
27
27
  def initialize(rep)
28
28
  initialize_teams_info(rep[:Teams])
29
- @subdivisions = rep[:Subdivisions]&.map { |s| s[:name] } || []
29
+ @tracks = rep[:Tracks]&.map { |s| s[:name] } || []
30
30
  @placings = rep[:Placings].group_by { |p| p[:team] }
31
31
  @exempt = rep[:Tournament][:'exempt placings'] || 0
32
32
  end
@@ -74,18 +74,18 @@ module SciolyFF
74
74
  "exempt placings (#{count} insteand of #{@exempt})"
75
75
  end
76
76
 
77
- def matching_subdivision?(team, logger)
78
- sub = team[:subdivision]
79
- return true if sub.nil? || @subdivisions.include?(sub)
77
+ def matching_track?(team, logger)
78
+ sub = team[:track]
79
+ return true if sub.nil? || @tracks.include?(sub)
80
80
 
81
- logger.error "'subdivision: #{sub}' does not match any name in "\
82
- 'section Subdivisions'
81
+ logger.error "'track: #{sub}' does not match any name in "\
82
+ 'section Tracks'
83
83
  end
84
84
 
85
- def in_a_subdivision_if_possible?(team, logger)
86
- return true unless !@subdivisions.empty? && !team[:subdivision]
85
+ def in_a_track_if_possible?(team, logger)
86
+ return true unless !@tracks.empty? && !team[:track]
87
87
 
88
- logger.warn "missing subdivision for 'team: #{team[:number]}'"
88
+ logger.warn "missing track for 'team: #{team[:number]}'"
89
89
  end
90
90
 
91
91
  include Validator::Canonical
@@ -16,7 +16,7 @@ module SciolyFF
16
16
  }.freeze
17
17
 
18
18
  OPTIONAL = {
19
- Subdivisions: Array,
19
+ Tracks: Array,
20
20
  Penalties: Array
21
21
  }.freeze
22
22
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sciolyff/validator/checker'
4
+ require 'sciolyff/validator/sections'
5
+ require 'sciolyff/validator/range'
6
+
7
+ module SciolyFF
8
+ # Checks for one track in the Tracks section of a SciolyFF file
9
+ class Validator::Tracks < Validator::Checker
10
+ include Validator::Sections
11
+
12
+ REQUIRED = {
13
+ name: String
14
+ }.freeze
15
+
16
+ OPTIONAL = {
17
+ medals: Integer,
18
+ trophies: Integer,
19
+ 'maximum place': Integer
20
+ }.freeze
21
+
22
+ def initialize(rep)
23
+ @names = rep[:Tracks].map { |s| s[:name] }
24
+ @teams = rep[:Teams].group_by { |t| t[:track] }
25
+ end
26
+
27
+ def unique_name?(track, logger)
28
+ return true if @names.count(track[:name]) == 1
29
+
30
+ logger.error "duplicate track name: #{track[:name]}"
31
+ end
32
+
33
+ def matching_teams?(track, logger)
34
+ name = track[:name]
35
+ return true if @teams[name]
36
+
37
+ logger.error "track with 'name: #{name}' has no teams"
38
+ end
39
+
40
+ include Validator::Range
41
+
42
+ def maximum_place_within_range?(track, logger)
43
+ max = team_count(track)
44
+ within_range?(track, :'maximum place', logger, 1, max)
45
+ end
46
+
47
+ def medals_within_range?(track, logger)
48
+ max = [team_count(track), track[:'maximum place']].compact.min
49
+ within_range?(track, :medals, logger, 1, max)
50
+ end
51
+
52
+ def trophies_within_range?(track, logger)
53
+ within_range?(track, :trophies, logger, 1, team_count(track))
54
+ end
55
+
56
+ private
57
+
58
+ def team_count(track)
59
+ @teams[track[:name]].count do |t|
60
+ t[:track] == track[:name] && !t[:exhibition]
61
+ end
62
+ end
63
+ end
64
+ end
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
9
9
  s.license = 'MIT'
10
10
  s.name = 'sciolyff-duosmium'
11
11
  s.summary = 'A file format for Science Olympiad tournament results.'
12
- s.version = '0.13.0'
12
+ s.version = '0.13.1'
13
13
  s.executables << 'sciolyff'
14
14
  s.add_runtime_dependency 'erubi', '~> 1.9'
15
15
  s.add_runtime_dependency 'optimist', '~> 3.0'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sciolyff-duosmium
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.13.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Em Zhan
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-12-12 00:00:00.000000000 Z
12
+ date: 2021-01-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: erubi
@@ -76,10 +76,10 @@ files:
76
76
  - lib/sciolyff/interpreter/penalty.rb
77
77
  - lib/sciolyff/interpreter/placing.rb
78
78
  - lib/sciolyff/interpreter/raw.rb
79
- - lib/sciolyff/interpreter/subdivisions.rb
80
79
  - lib/sciolyff/interpreter/team.rb
81
80
  - lib/sciolyff/interpreter/tiebreaks.rb
82
81
  - lib/sciolyff/interpreter/tournament.rb
82
+ - lib/sciolyff/interpreter/tracks.rb
83
83
  - lib/sciolyff/validator.rb
84
84
  - lib/sciolyff/validator/canonical.rb
85
85
  - lib/sciolyff/validator/checker.rb
@@ -90,10 +90,10 @@ files:
90
90
  - lib/sciolyff/validator/range.rb
91
91
  - lib/sciolyff/validator/raws.rb
92
92
  - lib/sciolyff/validator/sections.rb
93
- - lib/sciolyff/validator/subdivisions.rb
94
93
  - lib/sciolyff/validator/teams.rb
95
94
  - lib/sciolyff/validator/top_level.rb
96
95
  - lib/sciolyff/validator/tournament.rb
96
+ - lib/sciolyff/validator/tracks.rb
97
97
  - sciolyff.gemspec
98
98
  homepage: https://github.com/duosmium/sciolyff
99
99
  licenses:
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'sciolyff/validator/checker'
4
- require 'sciolyff/validator/sections'
5
- require 'sciolyff/validator/range'
6
-
7
- module SciolyFF
8
- # Checks for one subdivision in the Subdivisions section of a SciolyFF file
9
- class Validator::Subdivisions < Validator::Checker
10
- include Validator::Sections
11
-
12
- REQUIRED = {
13
- name: String
14
- }.freeze
15
-
16
- OPTIONAL = {
17
- medals: Integer,
18
- trophies: Integer,
19
- 'maximum place': Integer
20
- }.freeze
21
-
22
- def initialize(rep)
23
- @names = rep[:Subdivisions].map { |s| s[:name] }
24
- @teams = rep[:Teams].group_by { |t| t[:subdivision] }
25
- end
26
-
27
- def unique_name?(subdivision, logger)
28
- return true if @names.count(subdivision[:name]) == 1
29
-
30
- logger.error "duplicate subdivision name: #{subdivision[:name]}"
31
- end
32
-
33
- def matching_teams?(subdivision, logger)
34
- name = subdivision[:name]
35
- return true if @teams[name]
36
-
37
- logger.error "subdivision with 'name: #{name}' has no teams"
38
- end
39
-
40
- include Validator::Range
41
-
42
- def maximum_place_within_range?(subdivision, logger)
43
- max = team_count(subdivision)
44
- within_range?(subdivision, :'maximum place', logger, 1, max)
45
- end
46
-
47
- def medals_within_range?(subdivision, logger)
48
- max = [team_count(subdivision), subdivision[:'maximum place']].compact.min
49
- within_range?(subdivision, :medals, logger, 1, max)
50
- end
51
-
52
- def trophies_within_range?(subdivision, logger)
53
- within_range?(subdivision, :trophies, logger, 1, team_count(subdivision))
54
- end
55
-
56
- private
57
-
58
- def team_count(subdivision)
59
- @teams[subdivision[:name]].count do |t|
60
- t[:subdivision] == subdivision[:name] && !t[:exhibition]
61
- end
62
- end
63
- end
64
- end