diff --git a/mo/util.py b/mo/util.py
index f146deaf1edcf196e84c31ba585bc0b170335bff..b61bda90fd9dd84f19e1734cb3e566499935f2c5 100644
--- a/mo/util.py
+++ b/mo/util.py
@@ -159,12 +159,16 @@ def parse_gen_points(
 ) -> Tuple[str, Optional[decimal.Decimal], Optional[str]]:
     """Zobecnění parse_points(). Naparsuje generalizované body používané při editaci.
     Vrátí typ hodnocení, body (decimal.Decimal nebo None) a případný error."""
+    gen_points = gen_points.upper()
     if gen_points is None or gen_points == 'X':
         # Řešení nemá existovat
         return 'X', None, None
     elif gen_points == "" or gen_points == '?':
         # Řešení má existovat, ale nemá přidělené body
         return 'N', None, None
+    elif gen_points == 'P':
+        # Prázdný protokol
+        return 'P', decimal.Decimal(0), None
     else:
         # Řešení je ohodnoceno
         try:
diff --git a/mo/web/jinja.py b/mo/web/jinja.py
index 3ea87cdb12c96049c689618df592bc2dea593a98..ad4c519df57ca6ddd2d0df7deb6b7555b7e1ef13 100644
--- a/mo/web/jinja.py
+++ b/mo/web/jinja.py
@@ -141,6 +141,8 @@ def user_flags(u: db.User) -> Markup:
 def sol_editable_points(s: Optional[db.Solution]) -> str:
     if s is None:
         return 'X'
+    elif s.is_empty:
+        return 'P'
     elif s.points is None:
         return ""
     else:
@@ -148,10 +150,15 @@ def sol_editable_points(s: Optional[db.Solution]) -> str:
 
 
 @app.template_filter()
-def sol_display_points(s: Optional[db.Solution]) -> Union[str, Markup]:
+def sol_display_points(s: Optional[db.Solution], user: bool = False) -> Union[str, Markup]:
     if s is None:
         return '–'
+    elif s.is_empty:
+        return Markup('<span title="Prázdný protokol">∅</span>')
     elif s.points is None:
-        return Markup('<span class="unknown">?</span>')
+        if user:
+            return '–'
+        else:
+            return Markup('<span class="unknown">?</span>')
     else:
         return util_format.format_decimal(s.points)