Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Odevzdávací Systém MO
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Model registry
Analyze
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Martin Mareš
Odevzdávací Systém MO
Commits
7653de02
Commit
7653de02
authored
1 year ago
by
Martin Mareš
Browse files
Options
Downloads
Patches
Plain Diff
Points: Obecný modul na zacházení s hodnocením řešení
Vše kolem gen_points přesouvám sem.
parent
5e5d5980
Branches
Branches containing commit
No related tags found
1 merge request
!134
Prázdné protokoly
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
mo/points.py
+154
-0
154 additions, 0 deletions
mo/points.py
mo/util.py
+0
-29
0 additions, 29 deletions
mo/util.py
with
154 additions
and
29 deletions
mo/points.py
0 → 100644
+
154
−
0
View file @
7653de02
from
dataclasses
import
dataclass
,
field
from
decimal
import
Decimal
,
InvalidOperation
from
enum
import
auto
from
typing
import
Optional
,
Tuple
,
List
import
mo.db
as
db
import
mo.rights
import
mo.util
from
mo.util
import
assert_not_none
import
mo.util_format
@dataclass
class
GenPoints
:
have_solution
:
bool
=
True
is_empty
:
bool
=
False
points
:
Optional
[
Decimal
]
=
None
error
:
Optional
[
str
]
=
None
@staticmethod
def
parse
(
inp
:
Optional
[
str
],
for_task
:
Optional
[
db
.
Task
]
=
None
,
for_round
:
Optional
[
db
.
Round
]
=
None
,
)
->
'
GenPoints
'
:
"""
Zobecnění mo.util.parse_points(). Naparsuje generalizované body používané při editaci.
"""
inp
=
inp
.
upper
()
if
inp
is
not
None
else
None
gp
=
GenPoints
()
if
inp
is
None
or
inp
==
'
X
'
:
gp
.
have_solution
=
False
return
gp
if
inp
==
""
or
inp
==
'
?
'
:
pass
elif
inp
==
'
P
'
:
gp
.
is_empty
=
True
gp
.
points
=
Decimal
(
0
)
else
:
try
:
gp
.
points
=
Decimal
(
inp
.
replace
(
'
,
'
,
'
.
'
))
except
InvalidOperation
:
gp
.
error
=
f
"
Hodnota
'
{
inp
}
'
není číslo ani X nebo P
"
return
gp
gp
.
error
=
mo
.
util
.
check_points
(
gp
.
points
,
for_task
,
for_round
)
return
gp
class
SolActionError
(
RuntimeError
):
pass
@dataclass
class
SolAction
:
task
:
db
.
Task
user
:
db
.
User
sol
:
Optional
[
db
.
Solution
]
gp
:
GenPoints
reason
:
str
rights
:
mo
.
rights
.
RoundRights
to_log
:
List
[
str
]
allow_add_del
:
bool
=
True
did_add_or_del
:
bool
=
False
def
add_or_del
(
self
)
->
Tuple
[
bool
,
bool
]:
if
(
self
.
sol
is
not
None
)
==
self
.
gp
.
have_solution
:
return
False
,
False
sess
=
db
.
get_session
()
self
.
did_add_or_del
=
True
if
self
.
sol
is
None
:
if
not
self
.
allow_add_del
:
raise
SolActionError
(
'
Tento soutěžící úlohu neodevzdal
'
)
if
not
(
self
.
rights
.
can_upload_solutions
()
or
self
.
rights
.
can_upload_feedback
()):
raise
SolActionError
(
'
Nemáte právo na zakládání nových řešení, můžete jen upravovat body
'
)
self
.
sol
=
db
.
Solution
(
user
=
self
.
user
,
task
=
self
.
task
)
sess
.
add
(
self
.
sol
)
self
.
to_log
.
append
(
f
'
Založeno řešení user=#
{
self
.
user
.
user_id
}
task=#
{
self
.
task
.
task_id
}
'
)
mo
.
util
.
log
(
type
=
db
.
LogType
.
participant
,
what
=
self
.
user
.
user_id
,
details
=
{
'
action
'
:
'
solution-created
'
,
'
task
'
:
self
.
task
.
task_id
,
'
reason
'
:
self
.
reason
},
)
return
True
,
False
else
:
if
not
self
.
allow_add_del
:
raise
SolActionError
(
'
Tento soutěžící úlohu odevzdal
'
)
if
self
.
sol
.
final_submit
is
not
None
or
self
.
sol
.
final_feedback
is
not
None
:
raise
SolActionError
(
'
Nelze smazat řešení, ke kterému existují odevzdané soubory
'
)
if
not
self
.
rights
.
can_upload_solutions
():
raise
SolActionError
(
'
Nemáte právo na mazání řešení
'
)
self
.
to_log
.
append
(
f
'
Smazáno řešení user=#
{
self
.
user
.
user_id
}
task=#
{
self
.
task
.
task_id
}
'
)
mo
.
util
.
log
(
type
=
db
.
LogType
.
participant
,
what
=
self
.
user
.
user_id
,
details
=
{
'
action
'
:
'
solution-removed
'
,
'
task
'
:
self
.
task
.
task_id
,
'
reason
'
:
self
.
reason
},
)
sess
.
delete
(
self
.
sol
)
self
.
sol
=
None
return
False
,
True
def
set_points
(
self
)
->
bool
:
sol
=
self
.
sol
gp
=
self
.
gp
if
sol
is
None
:
return
False
if
gp
.
is_empty
==
sol
.
is_empty
and
gp
.
points
==
sol
.
points
:
return
False
if
not
self
.
rights
.
can_edit_points
():
raise
SolActionError
(
'
Nemáte právo hodnotit řešení
'
)
sol
.
points
=
gp
.
points
sol
.
is_empty
=
gp
.
is_empty
sess
=
db
.
get_session
()
sess
.
add
(
db
.
PointsHistory
(
task
=
self
.
task
,
participant_id
=
self
.
user
.
user_id
,
user
=
mo
.
util
.
current_log_user
,
points_at
=
mo
.
now
,
points
=
gp
.
points
,
is_empty
=
gp
.
is_empty
,
))
return
True
def
log_changes
(
self
):
sess
=
db
.
get_session
()
if
self
.
sol
and
not
self
.
did_add_or_del
and
sess
.
is_modified
(
self
.
sol
):
changes
=
db
.
get_object_changes
(
self
.
sol
)
mo
.
util
.
log
(
type
=
db
.
LogType
.
participant
,
what
=
self
.
user
.
user_id
,
details
=
{
'
action
'
:
'
solution-edit
'
,
'
task
'
:
self
.
task
.
task_id
,
'
changes
'
:
changes
,
'
reason
'
:
self
.
reason
,
},
)
self
.
to_log
.
append
(
f
"
Řešení user=#
{
self
.
user
.
user_id
}
task=#
{
self
.
task
.
task_id
}
modifikováno, změny:
{
changes
}
"
)
def
format_sol_editable_points
(
s
:
Optional
[
db
.
Solution
],
none_is_qmark
:
bool
=
False
)
->
str
:
if
s
is
None
:
return
'
X
'
elif
s
.
is_empty
:
return
'
P
'
elif
s
.
points
is
None
:
return
'
?
'
if
none_is_qmark
else
""
else
:
return
assert_not_none
(
mo
.
util_format
.
format_decimal
(
s
.
points
))
This diff is collapsed.
Click to expand it.
mo/util.py
+
0
−
29
View file @
7653de02
...
...
@@ -4,7 +4,6 @@ from dataclasses import dataclass
import
datetime
import
decimal
import
dateutil.tz
from
enum
import
auto
import
locale
import
logging
import
os
...
...
@@ -155,34 +154,6 @@ def parse_points(
return
points
,
check_points
(
points
,
for_task
,
for_round
)
class
GPAction
(
db
.
MOEnum
):
no_solution
=
auto
()
no_points
=
auto
()
is_empty
=
auto
()
has_points
=
auto
()
def
parse_gen_points
(
gen_points
:
Optional
[
str
],
for_task
:
Optional
[
db
.
Task
]
=
None
,
for_round
:
Optional
[
db
.
Round
]
=
None
,
)
->
Tuple
[
GPAction
,
Optional
[
decimal
.
Decimal
],
Optional
[
str
]]:
"""
Zobecnění parse_points(). Naparsuje generalizované body používané při editaci.
Vrátí typ hodnocení (GPAction), body (decimal.Decimal nebo None) a případný error.
"""
gen_points
=
gen_points
.
upper
()
if
gen_points
is
not
None
else
None
if
gen_points
is
None
or
gen_points
==
'
X
'
:
return
GPAction
.
no_solution
,
None
,
None
elif
gen_points
==
""
or
gen_points
==
'
?
'
:
# Řešení má existovat, ale nemá přidělené body
return
GPAction
.
no_points
,
None
,
None
elif
gen_points
==
'
P
'
:
return
GPAction
.
is_empty
,
decimal
.
Decimal
(
0
),
None
else
:
try
:
points
=
decimal
.
Decimal
(
gen_points
.
replace
(
'
,
'
,
'
.
'
))
except
decimal
.
InvalidOperation
:
return
""
,
decimal
.
Decimal
(
0
),
f
"
Hodnota
'
{
gen_points
}
'
není číslo ani X
"
return
GPAction
.
points
,
points
,
check_points
(
points
,
for_task
,
for_round
)
def
check_points
(
points
:
decimal
.
Decimal
,
for_task
:
Optional
[
db
.
Task
]
=
None
,
for_round
:
Optional
[
db
.
Round
]
=
None
)
->
Optional
[
str
]:
"""
Zkontroluje body. Pokud je vše ok, tak vrátí None, jinak vrátí text chyby.
"""
if
points
<
0
:
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment