(function (window, document, $) {
'use strict';
if (!$) { return; }
var timers = {};
var observerStarted = false;
var radioCounter = 0;
function intValue(value, fallback) {
var n = parseInt(value, 10);
if (isNaN(n)) { return typeof fallback === 'number' ? fallback : 0; }
return Math.max(0, n);
}
function pageText($page, key) {
var value = $page.attr('data-text-' + key);
return typeof value === 'string' ? value : '';
}
function parseModel($page) {
var $script = $page.find('#awardsPlannerModel');
if (!$script.length) { return {}; }
try {
return JSON.parse($script.text() || '{}');
} catch (e) {
return {};
}
}
function overrideKey(categoryId, levelId, danceId) {
return [intValue(categoryId), intValue(levelId), intValue(danceId)].join(':');
}
function ageOverrideKey(categoryId, levelId, danceId, ageGroupId) {
return [intValue(categoryId), intValue(levelId), intValue(danceId), intValue(ageGroupId)].join(':');
}
function getState($page) {
var state = $page.data('awardsPlannerState');
if (state) { return state; }
var model = parseModel($page);
state = {
model: model,
leaves: model.leaves || [],
selectors: model.selectors || [],
categoryLabels: model.category_labels || {},
overrides: $.extend(true, {}, model.overrides || {}),
leafIndex: {},
selectorIndex: {}
};
$.each(state.leaves, function (_, leaf) {
state.leafIndex[overrideKey(leaf.category_id, leaf.level_id, leaf.dance_id)] = leaf;
});
$.each(state.selectors, function (_, category) {
state.selectorIndex[String(category.id)] = category;
});
$page.data('awardsPlannerState', state);
return state;
}
function emptyResult() {
return { gold:0, silver:0, bronze:0, participation:0, cup_1:0, cup_2:0, cup_3:0 };
}
function addResult(target, source) {
$.each(['gold','silver','bronze','participation','cup_1','cup_2','cup_3'], function (_, key) {
target[key] += intValue(source[key]);
});
return target;
}
function emptyStats() {
return { competitions:0, entries:0, teams:0, planned_dancers:0 };
}
function statsForCompetitions(competitions) {
var stats = emptyStats();
$.each(competitions || [], function (_, competition) {
var entries = intValue(competition.entries);
if (!entries) { return; }
stats.competitions += 1;
stats.entries += entries;
if (competition.type === 'team') {
var teamSize = Math.max(1, intValue(competition.team_size, 1));
stats.teams += entries;
stats.planned_dancers += entries * teamSize;
}
});
return stats;
}
function cloneSettings(settings) {
settings = settings || {};
return {
cup_mode: settings.cup_mode || 'none',
team_medal_mode: settings.team_medal_mode || 'placements',
award_all: !!settings.award_all,
depth_mode: settings.depth_mode === 'threshold' ? 'threshold' : 'fixed',
fixed_places: Math.max(1, intValue(settings.fixed_places, 6)),
threshold_entries: Math.max(1, intValue(settings.threshold_entries, 5)),
threshold_low_places: Math.max(1, intValue(settings.threshold_low_places, 5)),
threshold_high_places: Math.max(1, intValue(settings.threshold_high_places, 6)),
override_enabled: intValue(settings.override_enabled) === 1 ? 1 : 0
};
}
function readSettings($scope) {
return {
cup_mode: $scope.find('.awards-cup-mode').val() || 'none',
team_medal_mode: $scope.find('.awards-team-medal-mode').val() || 'placements',
award_all: $scope.find('.awards-award-all').is(':checked'),
depth_mode: $scope.find('.awards-depth-mode:checked').val() || 'fixed',
fixed_places: Math.max(1, intValue($scope.find('.awards-fixed-places').val(), 1)),
threshold_entries: Math.max(1, intValue($scope.find('.awards-threshold-entries').val(), 1)),
threshold_low_places: Math.max(1, intValue($scope.find('.awards-threshold-low').val(), 1)),
threshold_high_places: Math.max(1, intValue($scope.find('.awards-threshold-high').val(), 1))
};
}
function writeSettings($scope, settings) {
settings = cloneSettings(settings);
$scope.find('.awards-cup-mode').val(settings.cup_mode);
$scope.find('.awards-team-medal-mode').val(settings.team_medal_mode);
$scope.find('.awards-award-all').prop('checked', !!settings.award_all);
$scope.find('.awards-depth-mode[value="' + settings.depth_mode + '"]').prop('checked', true);
$scope.find('.awards-fixed-places').val(settings.fixed_places);
$scope.find('.awards-threshold-entries').val(settings.threshold_entries);
$scope.find('.awards-threshold-low').val(settings.threshold_low_places);
$scope.find('.awards-threshold-high').val(settings.threshold_high_places);
}
function updateQuantityUI($scope, active) {
var awardAll = $scope.find('.awards-award-all').is(':checked');
var mode = $scope.find('.awards-depth-mode:checked').val() || 'fixed';
var quantityDisabled = !active || awardAll;
$scope.toggleClass('is-settings-disabled', !active);
$scope.find('.awards-cup-mode').prop('disabled', !active);
var isTeam = $scope.attr('data-is-team') === '1';
$scope.find('.awards-team-medal-mode').prop('disabled', !active || !isTeam);
$scope.find('.awards-team-setting-block').toggleClass('is-not-applicable', !isTeam);
$scope.find('.awards-award-all').prop('disabled', !active);
$scope.find('.awards-all-toggle')
.toggleClass('is-active', awardAll)
.toggleClass('is-control-disabled', !active);
$scope.find('.awards-depth-settings').toggleClass('is-disabled', quantityDisabled);
$scope.find('.awards-depth-mode').prop('disabled', quantityDisabled);
$scope.find('.awards-fixed-panel').toggleClass('is-hidden', mode !== 'fixed');
$scope.find('.awards-threshold-panel').toggleClass('is-hidden', mode !== 'threshold');
$scope.find('.awards-fixed-places').prop('disabled', quantityDisabled || mode !== 'fixed');
$scope.find('.awards-threshold-entries, .awards-threshold-low, .awards-threshold-high')
.prop('disabled', quantityDisabled || mode !== 'threshold');
}
function normalizeNumericInput($input) {
if ($input.val() === '') { return; }
$input.val(Math.max(1, intValue($input.val(), 1)));
}
function awardedPlaces(entries, settings) {
entries = intValue(entries);
if (!entries) { return 0; }
if (settings.award_all) { return entries; }
var places = settings.depth_mode === 'threshold'
? (entries <= settings.threshold_entries ? settings.threshold_low_places : settings.threshold_high_places)
: settings.fixed_places;
return Math.min(entries, Math.max(1, intValue(places, 1)));
}
function calculateCompetitions(competitions, settings) {
var result = emptyResult();
settings = cloneSettings(settings);
$.each(competitions || [], function (_, comp) {
var entries = intValue(comp.entries);
if (!entries) { return; }
var awarded = awardedPlaces(entries, settings);
if (!awarded) { return; }
if (comp.type === 'team') {
var teamSize = Math.max(1, intValue(comp.team_size, 1));
if (settings.team_medal_mode === 'participation') {
result.participation += awarded * teamSize;
} else {
if (awarded >= 1) { result.gold += teamSize; }
if (awarded >= 2) { result.silver += teamSize; }
if (awarded >= 3) { result.bronze += teamSize; }
if (awarded > 3) { result.participation += (awarded - 3) * teamSize; }
}
if ((settings.cup_mode === 'first' || settings.cup_mode === 'top3') && awarded >= 1) { result.cup_1 += 1; }
if (settings.cup_mode === 'top3' && awarded >= 2) { result.cup_2 += 1; }
if (settings.cup_mode === 'top3' && awarded >= 3) { result.cup_3 += 1; }
return;
}
if (awarded >= 1) {
if (settings.cup_mode === 'first' || settings.cup_mode === 'top3') { result.cup_1 += 1; }
else { result.gold += 1; }
}
if (awarded >= 2) {
if (settings.cup_mode === 'top3') { result.cup_2 += 1; }
else { result.silver += 1; }
}
if (awarded >= 3) {
if (settings.cup_mode === 'top3') { result.cup_3 += 1; }
else { result.bronze += 1; }
}
if (awarded > 3) { result.participation += awarded - 3; }
});
return result;
}
function mainRowForLeaf($page, leaf) {
return $page.find('.awards-main-row[data-main-key="' + String(leaf.main_key).replace(/"/g, '\\"') + '"]').first();
}
function baseSettingsForLeaf($page, leaf) {
var $row = mainRowForLeaf($page, leaf);
if (!$row.length) { return cloneSettings({}); }
return cloneSettings(readSettings($row));
}
function leafSettingsForLeaf($page, state, leaf) {
var key = overrideKey(leaf.category_id, leaf.level_id, leaf.dance_id);
var override = state.overrides[key];
if (override && intValue(override.override_enabled) === 1) {
return cloneSettings(override);
}
return baseSettingsForLeaf($page, leaf);
}
function effectiveSettingsForCompetition($page, state, leaf, competition) {
var settings = leafSettingsForLeaf($page, state, leaf);
var ageGroupId = intValue(competition && competition.age_group_id);
if (ageGroupId > 0) {
var key = ageOverrideKey(leaf.category_id, leaf.level_id, leaf.dance_id, ageGroupId);
var override = state.overrides[key];
if (override && intValue(override.override_enabled) === 1) {
return cloneSettings(override);
}
}
return settings;
}
function writeResult($row, result) {
$row.find('.awards-gold').text(intValue(result.gold));
$row.find('.awards-silver').text(intValue(result.silver));
$row.find('.awards-bronze').text(intValue(result.bronze));
$row.find('.awards-participation').text(intValue(result.participation));
$row.find('.awards-cup-1').text(intValue(result.cup_1));
$row.find('.awards-cup-2').text(intValue(result.cup_2));
$row.find('.awards-cup-3').text(intValue(result.cup_3));
}
function writeStats($page, $row, stats, isTeam) {
var html = '
' + intValue(stats.competitions) + ' ' + escapeHtml(pageText($page,'competitions')) + '
';
if (isTeam) {
html += '' + intValue(stats.teams) + ' ' + escapeHtml(pageText($page,'teams')) + '
';
html += '' + intValue(stats.planned_dancers) + ' ' + escapeHtml(pageText($page,'planned-dancers')) + '
';
} else {
html += '' + intValue(stats.entries) + ' ' + escapeHtml(pageText($page,'total-entries')) + '
';
}
$row.find('.awards-stats-cell').html(html);
}
function escapeHtml(value) {
return $('').text(value == null ? '' : value).html();
}
function breakdownHtml($page, items) {
if (!items.length) {
return '
' + escapeHtml(pageText($page,'no-cups')) + '
';
}
var html = '';
$.each(items, function (_, item) {
html += '
' + escapeHtml(item.label) + '' + intValue(item.value) + '
';
});
return html;
}
function formatMemoText(template, values) {
var index = 0;
return String(template || '').replace(/%s/g, function () {
var value = index < values.length ? values[index] : '';
index += 1;
return String(value);
});
}
function memoDepthText($page, settings) {
settings = cloneSettings(settings);
if (settings.award_all) {
return pageText($page,'award-all-participants');
}
if (settings.depth_mode === 'threshold') {
return formatMemoText(pageText($page,'threshold-depth'), [
settings.threshold_entries,
settings.threshold_low_places,
settings.threshold_entries,
settings.threshold_high_places
]);
}
return formatMemoText(pageText($page,'award-through'), [settings.fixed_places]);
}
function memoCupText($page, settings) {
if (settings.cup_mode === 'first') { return pageText($page,'cup-first'); }
if (settings.cup_mode === 'top3') { return pageText($page,'cup-top3'); }
return pageText($page,'cup-none');
}
function memoRuleText($page, settings, isTeam) {
settings = cloneSettings(settings);
var pieces = [memoDepthText($page,settings)];
if (isTeam) {
if (settings.team_medal_mode === 'participation') {
pieces.push(pageText($page,'team-participation'));
} else {
pieces.push(pageText($page,'medal-places'));
}
pieces.push(memoCupText($page,settings));
if (settings.cup_mode !== 'none') {
pieces.push(pageText($page,'team-cup-hint'));
}
} else if (settings.cup_mode === 'first') {
pieces.push(pageText($page,'solo-cup-first-rule'));
} else if (settings.cup_mode === 'top3') {
pieces.push(pageText($page,'solo-cup-top3-rule'));
} else {
pieces.push(pageText($page,'medal-places'));
pieces.push(pageText($page,'cup-none'));
}
return $.grep(pieces,function (piece) { return $.trim(piece || '') !== ''; }).join('. ') + '.';
}
function mainMemoLabel($row) {
var group = $.trim($row.find('.awards-row-group-label').first().text());
var name = $.trim($row.find('.awards-main-name').first().text());
if (group && name) { return group + ' / ' + name; }
return name || group;
}
function buildMemoData($page) {
var data = {
title: pageText($page,'memo-title'),
description: pageText($page,'memo-description'),
generalTitle: pageText($page,'memo-general'),
overridesTitle: pageText($page,'memo-overrides'),
general: [],
overrides: []
};
$page.find('.awards-main-row').each(function () {
var $row = $(this);
data.general.push({
label: mainMemoLabel($row),
rule: memoRuleText($page,readSettings($row),intValue($row.attr('data-is-team')) === 1),
override: false
});
});
$page.find('.awards-override-row').each(function () {
var $row = $(this);
data.overrides.push({
label: $.trim($row.find('.awards-override-row-path').first().text()),
rule: memoRuleText($page,readSettings($row),intValue($row.attr('data-is-team')) === 1),
override: true
});
});
return data;
}
function renderMemo($page) {
var data = buildMemoData($page);
$page.data('awardsMemoData',data);
return data;
}
function wrapCanvasText(ctx, text, maxWidth) {
var paragraphs = String(text == null ? '' : text).split(/\n/);
var lines = [];
$.each(paragraphs,function (_,paragraph) {
var words = String(paragraph).split(/\s+/);
var line = '';
$.each(words,function (_,word) {
if (!word) { return; }
var test = line ? line + ' ' + word : word;
if (ctx.measureText(test).width <= maxWidth) {
line = test;
return;
}
if (line) { lines.push(line); }
line = word;
if (ctx.measureText(line).width > maxWidth) {
var part = '';
$.each(line.split(''),function (_,character) {
var next = part + character;
if (ctx.measureText(next).width > maxWidth && part) {
lines.push(part);
part = character;
} else {
part = next;
}
});
line = part;
}
});
if (line) { lines.push(line); }
if (!words.length) { lines.push(''); }
});
return lines.length ? lines : [''];
}
function memoPdfCanvases($page, data) {
var width = 1240;
var height = 1754;
var marginX = 92;
var marginTop = 78;
var marginBottom = 78;
var contentWidth = width - (marginX * 2);
var pages = [];
var canvas;
var ctx;
var y;
var pageNumber = 0;
function startPage(isFirst) {
canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext('2d');
ctx.fillStyle = '#ffffff';
ctx.fillRect(0,0,width,height);
ctx.textBaseline = 'top';
y = marginTop;
pageNumber += 1;
ctx.fillStyle = '#182733';
ctx.font = '700 34px Arial, sans-serif';
$.each(wrapCanvasText(ctx,data.title,contentWidth),function (_,line) {
ctx.fillText(line,marginX,y);
y += 43;
});
if (isFirst && data.description) {
y += 7;
ctx.fillStyle = '#5d6b73';
ctx.font = '400 19px Arial, sans-serif';
$.each(wrapCanvasText(ctx,data.description,contentWidth),function (_,line) {
ctx.fillText(line,marginX,y);
y += 28;
});
}
y += 26;
pages.push(canvas);
}
function pageHasRoom(required) {
return y + required <= height - marginBottom;
}
function drawGroupTitle(title) {
var required = 48;
if (!pageHasRoom(required)) { startPage(false); }
ctx.fillStyle = '#315f86';
ctx.font = '700 23px Arial, sans-serif';
ctx.fillText(title,marginX,y);
y += 38;
}
function drawRow(row, isOverride) {
ctx.font = '700 20px Arial, sans-serif';
var nameLines = wrapCanvasText(ctx,row.label,contentWidth - 36);
ctx.font = '400 18px Arial, sans-serif';
var ruleLines = wrapCanvasText(ctx,row.rule,contentWidth - 36);
var nameIndex = 0;
var ruleIndex = 0;
var labelComplete = false;
while (nameIndex < nameLines.length || ruleIndex < ruleLines.length) {
var minFragmentHeight = 78;
if (!pageHasRoom(minFragmentHeight)) { startPage(false); }
var available = (height - marginBottom) - y;
var topPadding = 15;
var bottomPadding = 15;
var gap = 8;
var fragmentName = [];
var fragmentRule = [];
var used = topPadding + bottomPadding;
if (!labelComplete) {
while (nameIndex < nameLines.length && used + 27 <= available) {
fragmentName.push(nameLines[nameIndex]);
nameIndex += 1;
used += 27;
}
labelComplete = nameIndex >= nameLines.length;
if (labelComplete && ruleIndex < ruleLines.length && used + gap + 25 <= available) {
used += gap;
}
}
if (labelComplete) {
while (ruleIndex < ruleLines.length && used + 25 <= available) {
fragmentRule.push(ruleLines[ruleIndex]);
ruleIndex += 1;
used += 25;
}
}
if (!fragmentName.length && !fragmentRule.length) {
startPage(false);
continue;
}
var fragmentHeight = Math.max(minFragmentHeight,used);
ctx.fillStyle = isOverride ? '#fff7e6' : '#f7fafc';
ctx.strokeStyle = isOverride ? '#d8b46a' : '#d9e2e8';
ctx.lineWidth = 2;
ctx.fillRect(marginX,y,contentWidth,fragmentHeight - 8);
ctx.strokeRect(marginX,y,contentWidth,fragmentHeight - 8);
var textX = marginX + 18;
var textY = y + topPadding;
if (fragmentName.length) {
ctx.fillStyle = '#23343f';
ctx.font = '700 20px Arial, sans-serif';
$.each(fragmentName,function (_,line) {
ctx.fillText(line,textX,textY);
textY += 27;
});
if (fragmentRule.length) { textY += gap; }
}
if (fragmentRule.length) {
ctx.fillStyle = '#475861';
ctx.font = '400 18px Arial, sans-serif';
$.each(fragmentRule,function (_,line) {
ctx.fillText(line,textX,textY);
textY += 25;
});
}
y += fragmentHeight;
if (nameIndex < nameLines.length || ruleIndex < ruleLines.length) {
startPage(false);
}
}
}
function drawEmpty(text) {
ctx.font = '400 18px Arial, sans-serif';
var lines = wrapCanvasText(ctx,text,contentWidth);
var required = (lines.length * 25) + 20;
if (!pageHasRoom(required)) { startPage(false); }
ctx.fillStyle = '#7b878d';
$.each(lines,function (_,line) {
ctx.fillText(line,marginX,y);
y += 25;
});
y += 18;
}
startPage(true);
drawGroupTitle(data.generalTitle);
$.each(data.general,function (_,row) { drawRow(row,false); });
y += 10;
drawGroupTitle(data.overridesTitle);
if (data.overrides.length) {
$.each(data.overrides,function (_,row) { drawRow(row,true); });
} else {
drawEmpty(pageText($page,'no-overrides'));
}
$.each(pages,function (index,pageCanvas) {
var pageCtx = pageCanvas.getContext('2d');
pageCtx.fillStyle = '#7d898f';
pageCtx.font = '400 16px Arial, sans-serif';
var number = String(index + 1) + ' / ' + String(pages.length);
pageCtx.fillText(number,width - marginX - pageCtx.measureText(number).width,height - 48);
});
return pages;
}
function asciiBytes(text) {
var bytes = new Uint8Array(text.length);
for (var i = 0; i < text.length; i += 1) {
bytes[i] = text.charCodeAt(i) & 255;
}
return bytes;
}
function dataUrlBytes(dataUrl) {
var base64 = String(dataUrl).split(',')[1] || '';
var binary = window.atob(base64);
var bytes = new Uint8Array(binary.length);
for (var i = 0; i < binary.length; i += 1) {
bytes[i] = binary.charCodeAt(i);
}
return bytes;
}
function concatByteArrays(chunks) {
var total = 0;
$.each(chunks,function (_,chunk) { total += chunk.length; });
var result = new Uint8Array(total);
var offset = 0;
$.each(chunks,function (_,chunk) {
result.set(chunk,offset);
offset += chunk.length;
});
return result;
}
function buildRasterPdf(canvases) {
var pageWidth = 595.28;
var pageHeight = 841.89;
var objects = [];
var kids = [];
var pageCount = canvases.length;
objects[1] = asciiBytes('<< /Type /Catalog /Pages 2 0 R >>');
$.each(canvases,function (index,canvas) {
var pageObject = 3 + (index * 3);
var imageObject = pageObject + 1;
var contentObject = pageObject + 2;
var jpeg = dataUrlBytes(canvas.toDataURL('image/jpeg',0.92));
var content = 'q\n' + pageWidth + ' 0 0 ' + pageHeight + ' 0 0 cm\n/Im0 Do\nQ\n';
kids.push(pageObject + ' 0 R');
objects[pageObject] = asciiBytes(
'<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ' + pageWidth + ' ' + pageHeight + '] ' +
'/Resources << /XObject << /Im0 ' + imageObject + ' 0 R >> >> /Contents ' + contentObject + ' 0 R >>'
);
objects[imageObject] = concatByteArrays([
asciiBytes('<< /Type /XObject /Subtype /Image /Width ' + canvas.width + ' /Height ' + canvas.height + ' /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /DCTDecode /Length ' + jpeg.length + ' >>\nstream\n'),
jpeg,
asciiBytes('\nendstream')
]);
objects[contentObject] = asciiBytes('<< /Length ' + content.length + ' >>\nstream\n' + content + 'endstream');
});
objects[2] = asciiBytes('<< /Type /Pages /Count ' + pageCount + ' /Kids [' + kids.join(' ') + '] >>');
var chunks = [asciiBytes('%PDF-1.4\n')];
var offsets = [0];
var length = chunks[0].length;
var maxObject = objects.length - 1;
for (var objectNumber = 1; objectNumber <= maxObject; objectNumber += 1) {
offsets[objectNumber] = length;
var head = asciiBytes(objectNumber + ' 0 obj\n');
var body = objects[objectNumber];
var tail = asciiBytes('\nendobj\n');
chunks.push(head,body,tail);
length += head.length + body.length + tail.length;
}
var xrefOffset = length;
var xref = 'xref\n0 ' + (maxObject + 1) + '\n0000000000 65535 f \n';
for (var x = 1; x <= maxObject; x += 1) {
xref += ('0000000000' + String(offsets[x])).slice(-10) + ' 00000 n \n';
}
xref += 'trailer\n<< /Size ' + (maxObject + 1) + ' /Root 1 0 R >>\nstartxref\n' + xrefOffset + '\n%%EOF';
chunks.push(asciiBytes(xref));
return new Blob(chunks,{type:'application/pdf'});
}
function downloadMemoPdf($page) {
try {
var data = renderMemo($page);
var canvases = memoPdfCanvases($page,data);
var blob = buildRasterPdf(canvases);
var url = window.URL.createObjectURL(blob);
var link = document.createElement('a');
link.href = url;
link.download = 'awards_memo.pdf';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.setTimeout(function () { window.URL.revokeObjectURL(url); },1000);
} catch (error) {
if (window.console && console.error) { console.error('Awards memo PDF error',error); }
window.alert(pageText($page,'pdf-failed'));
}
}
function competitionsForOverrideRow(state, $row) {
var categoryId = intValue($row.attr('data-category-id'));
var levelId = intValue($row.attr('data-level-id'));
var danceId = intValue($row.attr('data-dance-id'));
var ageGroupId = intValue($row.attr('data-age-group-id'));
var leaf = state.leafIndex[overrideKey(categoryId, levelId, danceId)];
if (!leaf) { return []; }
if (!ageGroupId) { return leaf.competitions || []; }
return $.grep(leaf.competitions || [], function (competition) {
return intValue(competition.age_group_id) === ageGroupId;
});
}
function recalculateAll($page) {
if (!$page || !$page.length) { return; }
var state = getState($page);
var mainResults = {};
var categoryResults = {};
var summaryResults = {};
var totals = emptyResult();
$page.find('.awards-main-row').each(function () {
mainResults[$(this).attr('data-main-key')] = emptyResult();
});
$.each(state.leaves, function (_, leaf) {
var mainKey = String(leaf.main_key);
var categoryKey = String(leaf.category_id);
var categoryId = intValue(leaf.category_id);
var summaryKey;
var summaryLabel;
/*
* In the final cup breakdown Championship and Other dances are
* shown per dance. Every other category remains grouped only by
* category.
*/
if (categoryId === 4 || categoryId === 7) {
summaryKey = 'dance:' + categoryId + ':' + intValue(leaf.dance_id);
summaryLabel = leaf.dance_label
|| state.categoryLabels[categoryKey]
|| state.categoryLabels[categoryId]
|| categoryKey;
} else {
summaryKey = 'category:' + categoryId;
summaryLabel = state.categoryLabels[categoryKey]
|| state.categoryLabels[categoryId]
|| categoryKey;
}
if (!mainResults[mainKey]) { mainResults[mainKey] = emptyResult(); }
if (!categoryResults[categoryKey]) { categoryResults[categoryKey] = emptyResult(); }
if (!summaryResults[summaryKey]) {
summaryResults[summaryKey] = {
label: summaryLabel,
result: emptyResult()
};
}
$.each(leaf.competitions || [], function (_, competition) {
var settings = effectiveSettingsForCompetition($page, state, leaf, competition);
var calc = calculateCompetitions([competition], settings);
addResult(mainResults[mainKey], calc);
addResult(categoryResults[categoryKey], calc);
addResult(summaryResults[summaryKey].result, calc);
addResult(totals, calc);
});
});
$page.find('.awards-main-row').each(function () {
var $row = $(this);
var key = $row.attr('data-main-key');
writeResult($row, mainResults[key] || emptyResult());
});
$page.find('.awards-override-row').each(function () {
var $row = $(this);
var competitions = competitionsForOverrideRow(state, $row);
var settings = readSettings($row);
writeResult($row, calculateCompetitions(competitions, settings));
});
var totalMedals = totals.gold + totals.silver + totals.bronze + totals.participation;
$page.find('#awardsSummaryGold').text(totals.gold);
$page.find('#awardsSummarySilver').text(totals.silver);
$page.find('#awardsSummaryBronze').text(totals.bronze);
$page.find('#awardsSummaryParticipation').text(totals.participation);
$page.find('#awardsSummaryMedals').text(totalMedals);
$.each([1,2,3], function (_, place) {
var items = [];
var cupTotal = 0;
$.each(summaryResults, function (_, group) {
var value = intValue(group.result['cup_' + place]);
if (!value) { return; }
items.push({
label: group.label,
value: value
});
cupTotal += value;
});
$page.find('#awardsCup' + place + 'Breakdown').html(breakdownHtml($page, items));
$page.find('#awardsSummaryCup' + place).text(cupTotal);
});
renderMemo($page);
}
function setStatus($scope, state, text) {
var $status = $scope.find('.awards-save-status').first();
$status.removeClass('is-saving is-saved is-error');
if (state) { $status.addClass('is-' + state); }
$status.text(text || '');
}
function ajaxSave($page, payload, $statusScope) {
if ($statusScope && $statusScope.length) {
setStatus($statusScope,'saving',pageText($page,'saving'));
}
return $.ajax({
url: $page.attr('data-actions-url') || 'actions.php',
type: 'POST',
dataType: 'json',
data: $.extend({action:'save_award_scope_settings'}, payload)
}).done(function (response) {
if (!$statusScope || !$statusScope.length) { return; }
if (response && response.ok) {
setStatus($statusScope,'saved',pageText($page,'saved'));
} else {
setStatus($statusScope,'error',(response && response.error) || pageText($page,'save-failed'));
}
}).fail(function (xhr) {
if (!$statusScope || !$statusScope.length) { return; }
var error = pageText($page,'save-failed');
if (xhr.responseJSON && xhr.responseJSON.error) { error = xhr.responseJSON.error; }
setStatus($statusScope,'error',error);
});
}
function payloadFromScope($scope, overrideEnabled) {
var settings = readSettings($scope);
return {
scope_type: $scope.attr('data-scope-type') || 'category',
category_id: intValue($scope.attr('data-category-id')),
level_id: intValue($scope.attr('data-level-id')),
dance_id: intValue($scope.attr('data-dance-id')),
age_group_id: intValue($scope.attr('data-age-group-id')),
override_enabled: overrideEnabled ? 1 : 0,
cup_mode: settings.cup_mode,
team_medal_mode: settings.team_medal_mode,
award_all: settings.award_all ? 1 : 0,
depth_mode: settings.depth_mode,
fixed_places: settings.fixed_places,
threshold_entries: settings.threshold_entries,
threshold_low_places: settings.threshold_low_places,
threshold_high_places: settings.threshold_high_places
};
}
function saveMainRow($page, $row) {
return ajaxSave($page, payloadFromScope($row,true), $row);
}
function keyForOverrideRow($row) {
return String($row.attr('data-override-key') || '');
}
function saveOverrideRow($page, $row) {
var state = getState($page);
var key = keyForOverrideRow($row);
if (!key) { return $.Deferred().resolve().promise(); }
var settings = cloneSettings(readSettings($row));
settings.override_enabled = 1;
state.overrides[key] = settings;
return ajaxSave($page, payloadFromScope($row,true), $row);
}
function scheduleMainSave($page, $row) {
var key = 'main:' + ($row.attr('data-main-key') || '');
clearTimeout(timers[key]);
setStatus($row,'saving',pageText($page,'changed'));
timers[key] = setTimeout(function () { saveMainRow($page,$row); },450);
}
function scheduleOverrideSave($page, $row) {
var key = keyForOverrideRow($row);
var timerKey = 'override:' + key;
clearTimeout(timers[timerKey]);
setStatus($row,'saving',pageText($page,'changed'));
timers[timerKey] = setTimeout(function () { saveOverrideRow($page,$row); },450);
}
function findLevel(category, levelId) {
var found = null;
$.each((category && category.levels) || [], function (_, level) {
if (String(level.id) === String(levelId)) { found = level; return false; }
});
return found;
}
function findDance(level, danceId) {
var found = null;
$.each((level && level.dances) || [], function (_, dance) {
if (String(dance.id) === String(danceId)) { found = dance; return false; }
});
return found;
}
function findAgeGroup(leaf, ageGroupId) {
var found = null;
$.each((leaf && leaf.age_groups) || [], function (_, ageGroup) {
if (String(ageGroup.id) === String(ageGroupId)) { found = ageGroup; return false; }
});
return found;
}
function fillCategorySelect($page) {
var state = getState($page);
var $select = $page.find('#awardsOverrideCategory');
var selected = $select.val();
$select.empty().append($('