Compare commits

...

4 commits

Author SHA1 Message Date
Claudio Maggioni (maggicl)
139225a1f6 Added drag support on scores 2019-08-16 14:59:56 +02:00
Claudio Maggioni (maggicl)
19e4c62e50 Added mockup impact selection on scores 2019-08-12 23:51:45 +02:00
Claudio Maggioni (maggicl)
c7f7ad4f1b More work on score app 2019-08-07 14:47:24 +02:00
Claudio Maggioni (maggicl)
b5a133a3c2 Added models to score app 2019-08-07 12:44:12 +02:00
13 changed files with 264 additions and 0 deletions

View file

@ -44,6 +44,7 @@ STATIC_ROOT = "static/"
INSTALLED_APPS = [ INSTALLED_APPS = [
'counter.apps.CounterConfig', 'counter.apps.CounterConfig',
'user.apps.UserConfig', 'user.apps.UserConfig',
'score.apps.ScoreConfig',
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',

View file

@ -22,6 +22,7 @@ from django.views.i18n import JavaScriptCatalog
urlpatterns = i18n_patterns( urlpatterns = i18n_patterns(
path('', include('counter.urls')), path('', include('counter.urls')),
path('', include('score.urls')),
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('accounts/', include('user.urls')), path('accounts/', include('user.urls')),

0
score/__init__.py Normal file
View file

5
score/admin.py Normal file
View file

@ -0,0 +1,5 @@
from django.contrib import admin
from .models import Score, ScoreRow
admin.site.register(Score)
admin.site.register(ScoreRow)

5
score/apps.py Normal file
View file

@ -0,0 +1,5 @@
from django.apps import AppConfig
class ScoreConfig(AppConfig):
name = 'score'

View file

41
score/models.py Normal file
View file

@ -0,0 +1,41 @@
from django.db import models
from django.conf import settings
from django.contrib.auth.models import User
from django.utils.translation import gettext_lazy as _
from django.core.validators import RegexValidator, MaxValueValidator, \
MaxLengthValidator
class Score(models.Model):
TARGETS = [
('TR', _('40/60/80/120cm Target')),
('HF', _('H&F target'))
]
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
ends = models.PositiveSmallIntegerField(_('Number of ends in this score'),
validators=[MaxValueValidator(24)])
arrows_per_end = models.PositiveSmallIntegerField(
_('Number of arrows per end'), validators=[MaxValueValidator(12)])
date = models.DateField(_('Date of the score'))
notes = models.TextField(_('Additional notes'),
validators=[MaxLengthValidator(500)])
target = models.CharField(_('Type of target'), max_length=2,
choices=TARGETS)
class ScoreRow(models.Model):
class Meta:
unique_together = [['score', 'end_number']]
score = models.ForeignKey(Score, on_delete=models.CASCADE)
arrow_list = models.CharField(_('Comma separated list of arrow scores'),
max_length=36,
validators=[RegexValidator(regex="^(\d|10)(,(\d|10)){2,11}$",
message=_("Value given is not a valid score row"))])
end_number = models.PositiveSmallIntegerField(_('End number'),
validators=[MaxValueValidator(24)])

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://web.resource.org/cc/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.0" width="80cm" height="80cm" viewBox="-40 -40 80 80" id="svg2">
<metadata id="metadata18">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title>Official FITA 80cm Archery Target</dc:title>
<dc:date>2006-06-01</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Alberto Barbati</dc:title>
</cc:Agent>
</dc:creator>
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/"/>
<dc:subject>
<rdf:Bag>
<rdf:li>archery target</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:description>An official FITA 80cm archery target.
Real colors are:
Yellow: Pantone 107U
Red: Pantone 032U
Light blue: Pantone 306U</dc:description>
</cc:Work>
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
<cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
<cc:requires rdf:resource="http://web.resource.org/cc/Notice"/>
<cc:requires rdf:resource="http://web.resource.org/cc/Attribution"/>
<cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
<cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike"/>
</cc:License>
</rdf:RDF>
</metadata>
<circle cx="0" cy="0" r="39.9" fill="white" stroke="black" stroke-width="0.2" id="Zone1"/>
<circle cx="0" cy="0" r="35.9" fill="white" stroke="black" stroke-width="0.2" id="Zone2"/>
<circle cx="0" cy="0" r="32" fill="black" id="Zone3"/>
<circle cx="0" cy="0" r="27.9" fill="black" stroke="white" stroke-width="0.2" id="Zone4"/>
<circle cx="0" cy="0" r="24" fill="#41b7c8" id="Zone5"/>
<circle cx="0" cy="0" r="19.9" fill="#41b7c8" stroke="black" stroke-width="0.2" id="Zone6"/>
<circle cx="0" cy="0" r="15.9" fill="#fd1b14" stroke="black" stroke-width="0.2" id="Zone7"/>
<circle cx="0" cy="0" r="11.9" fill="#fd1b14" stroke="black" stroke-width="0.2" id="Zone8"/>
<circle cx="0" cy="0" r="7.9" fill="#fff535" stroke="black" stroke-width="0.2" id="Zone9"/>
<circle cx="0" cy="0" r="3.9" fill="#fff535" stroke="black" stroke-width="0.2" id="Zone10"/>
<circle cx="0" cy="0" r="1.9" fill="#fff535" stroke="black" stroke-width="0.1" id="Inner10"/>
<path d="M -0.2 0 L 0.2 0 M 0 -0.2 L 0 0.2" stroke="black" stroke-width="0.1" id="Center"/>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

76
score/static/js/score.js Normal file
View file

@ -0,0 +1,76 @@
// vim: set ts=2 sw=2 et tw=80:
$(document).ready(() => {
const TARGET_EVENTS = $('.target-events');
const SCORES = [
{ name: 'X', maxRadius: 0.025 },
{ name: '10', maxRadius: 0.05 },
{ name: '9', maxRadius: 0.1 },
{ name: '8', maxRadius: 0.15 },
{ name: '7', maxRadius: 0.2 },
{ name: '6', maxRadius: 0.25 },
{ name: '5', maxRadius: 0.3 },
{ name: '4', maxRadius: 0.35 },
{ name: '3', maxRadius: 0.4 },
{ name: '2', maxRadius: 0.45 },
{ name: '1', maxRadius: 0.5 }
];
function score(radius) {
for (let score of SCORES) {
if (radius <= score.maxRadius) {
return score.name;
}
}
return 'M';
};
TARGET_EVENTS.on('mousemove', e => {
if (TARGET_EVENTS.data('dragging')) {
const left = e.originalEvent.pageX - TARGET_EVENTS.offset().left;
const top = e.originalEvent.pageY - TARGET_EVENTS.offset().top;
markScore(left, top, TARGET_EVENTS.data('dragging')[0]);
}
});
TARGET_EVENTS.on('mouseup', e => {
let $marker = TARGET_EVENTS.data('dragging');
if ($marker) {
$marker.removeClass('orange');
$marker.addClass('teal');
TARGET_EVENTS.data('dragging', null);
} else {
markScore(e.originalEvent.offsetX, e.originalEvent.offsetY, false);
}
});
function markScore(left, top, marker) {
const targetRadius = TARGET_EVENTS.width();
const x = -0.5 + left / targetRadius;
const y = -0.5 + top / targetRadius;
const radius = Math.sqrt(x * x + y * y);
if (!marker) {
marker = document.createElement("div");
const $marker = $(marker);
$marker.on('mousedown', e => {
TARGET_EVENTS.data('dragging', $marker);
$marker.removeClass('teal');
$marker.addClass('orange');
e.preventDefault();
});
marker.className = "score-marker teal";
TARGET_EVENTS.append(marker);
}
marker.style.left = (x + 0.5) * 100 + "%";
marker.style.top = (y + 0.5) * 100 + "%";
console.log(x, y, score(radius));
};
});

View file

@ -0,0 +1,70 @@
{# vim: set ts=2 sw=2 et tw=80: #}
{% extends "base.html" %}
{% load static %}
{% load i18n %}
{% block title %}{% trans "Update score" %}{% endblock %}
{% block scripts %}
<script src="{% static "js/score.js" %}"></script>
{% endblock %}
{% block style %}
<style>
.target-container {
max-width: 450px;
max-height: 450px;
width: 100%;
height: 100%;
display: inline-block;
margin: 1rem;
position: relative;
}
.target-events, #target-svg {
z-index: 0;
width: 100%;
height: 100%;
border-radius: 50%;
}
.target-events {
position: absolute;
z-index: 1;
}
.target {
text-align: center;
}
.score-marker {
position: absolute;
width: 1em;
height: 1em;
margin-top: -.5em;
margin-left: -.5em;
border-radius: .5em;
border: 1px solid black;
z-index: 2;
}
</style>
{% endblock %}
{% block content %}
<h1 class="center edit-arrowcount title">{% trans "Update score" %}</h1>
<div class="card-panel grey lighten-1 target">
<div class='target-container'>
<div class='target-events'></div>
<object id="target-svg"
type="image/svg+xml" data="{% static "img/WA_target.svg" %}">
</object>
</div>
</div>
<div class="card grey lighten-2">
<div class="card-content center">
<span class="card-title">{% trans "Score" %}</span>
<p>lorem</p>
</div>
</div>
{% endblock %}

3
score/tests.py Normal file
View file

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

7
score/urls.py Normal file
View file

@ -0,0 +1,7 @@
from django.urls import path
from django.contrib.auth.decorators import login_required
from . import views
urlpatterns = [
path('score/edit/<int:sc_id>', views.score_edit, name='score_edit'),
]

6
score/views.py Normal file
View file

@ -0,0 +1,6 @@
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
@login_required
def score_edit(request, sc_id):
return render(request, 'score/edit.html', {})