Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Support multiple games #6

Draft
wants to merge 32 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
1fbff58
migrate models.py to models directory
ifalatik Sep 28, 2024
706aa5f
migrate Player class to CsPlayer and add abstract Player class
ifalatik Sep 29, 2024
9706932
Add note to PlayerRole class
ifalatik Sep 29, 2024
32a3edd
move comment to correct class
ifalatik Sep 29, 2024
885dcd6
rename Match -> CsMatch and Tournament -> CsTournament
ifalatik Sep 29, 2024
f94e7d0
Rename CSGOSiteSetting -> SiteSetting
ifalatik Sep 29, 2024
2babcec
finish migration Match -> CsMatch
ifalatik Sep 29, 2024
5d5cc77
cleanup urls.py
ifalatik Sep 29, 2024
d34c0a0
rename LineupPlayer -> CsLineupPlayer
ifalatik Sep 29, 2024
5a07a3f
add verbose_name and verbose_name_plural to all CS specific models
ifalatik Sep 29, 2024
d137d3e
migrate PlayerRole to Enum
ifalatik Sep 29, 2024
7e5a01b
fix relation between CsMatch and CsTournament in Match class
ifalatik Sep 29, 2024
d5969c8
improve str representation for LineupPlayer models
ifalatik Sep 29, 2024
876ae79
remove cs_name attribute from Map as it's game specific
ifalatik Sep 29, 2024
05e37aa
Rename MatchMap -> CsMatchMap
ifalatik Sep 29, 2024
6c5f796
add verbose names to CsMatchMap
ifalatik Sep 29, 2024
1b78279
reorganize Tournament - move Meta class up
ifalatik Sep 29, 2024
5dfd72e
add first_map_at to filter for similar_matches_in_same_tournament
ifalatik Sep 29, 2024
c2cc127
rename Map -> CsMap
ifalatik Sep 29, 2024
a8600e5
remove delay_minutes as it's used nowhere
ifalatik Sep 29, 2024
cdb1183
rename MatchMap.played_map -> map
ifalatik Sep 29, 2024
f084736
move parts of Match and MatchMap to respecive OneOnOne abtract model …
ifalatik Sep 29, 2024
5b61fd9
Rename Lineup -> CsLineup
ifalatik Sep 29, 2024
7e6189d
move all meta options to implementations instead of abstract models
ifalatik Sep 29, 2024
9f5ed23
properly inherit abstract Meta classes
ifalatik Sep 29, 2024
76762cb
Serializers and Views: Rename CSGO -> Cs
ifalatik Sep 29, 2024
cd2b68e
fix class name
ifalatik Dec 2, 2024
11c37fe
fix related_name property for lineup_set and matchmap_set in CS imple…
ifalatik Dec 2, 2024
823deb4
fix matchmap_set type annotation in Match model
ifalatik Dec 2, 2024
2a4eb1b
fix save method to use the correct model type for fetching previous i…
ifalatik Dec 2, 2024
4f1908e
migrate context_data scorelines to CS2 values
ifalatik Dec 2, 2024
1d81700
add new line
ifalatik Dec 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions csgomatches/admin.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from django.contrib import admin, messages
from django.utils.safestring import mark_safe

from . import models
from csgomatches import models


# Inlines
class LineupPlayerInline(admin.TabularInline):
model = models.LineupPlayer
class CsLineupPlayerInline(admin.TabularInline):
model = models.CsLineupPlayer
autocomplete_fields = ['player']
extra = 5
max_num = 5
Expand All @@ -17,8 +17,8 @@ class LineupInline(admin.TabularInline):
extra = 0


class MatchMapInline(admin.TabularInline):
model = models.MatchMap
class CsMatchMapInline(admin.TabularInline):
model = models.CsMatchMap
extra = 0
verbose_name = 'Map'
verbose_name_plural = 'Match Maps'
Expand All @@ -31,8 +31,8 @@ class ExternalLinkInline(admin.TabularInline):

# Models
class MatchMapAdmin(admin.ModelAdmin):
list_display = ['match', 'rounds_won_team_a', 'rounds_won_team_b', 'played_map', 'has_ended', 'is_live', 'delay_minutes', 'starting_at', 'unplayed', 'map_nr']
list_editable = ['rounds_won_team_a', 'rounds_won_team_b', 'played_map', 'map_nr']
list_display = ['match', 'rounds_won_team_a', 'rounds_won_team_b', 'map', 'has_ended', 'is_live', 'starting_at', 'unplayed', 'map_nr']
list_editable = ['rounds_won_team_a', 'rounds_won_team_b', 'map', 'map_nr']
list_filter = ['match__tournament', 'match__lineup_a', 'match__lineup_b', 'map_nr']

ordering = ['-starting_at']
Expand All @@ -48,7 +48,8 @@ def is_live(self, obj):
is_live.boolean = True


class TournamentAdmin(admin.ModelAdmin):
# Currently no generic implementation of ModelAdmin for Tournament class
class CsTournamentAdmin(admin.ModelAdmin):
search_fields = ['name', 'name_alt', 'name_hltv', 'name_99dmg']
list_display = ['name', 'name_alt', 'name_hltv', 'name_99dmg']
actions = ['cleanup', 'merge_two']
Expand Down Expand Up @@ -182,7 +183,7 @@ class LineupAdmin(admin.ModelAdmin):
list_display = ['team', 'game', 'team_logo_url', 'active_from', 'get_is_active', 'is_active']
autocomplete_fields = ['team']
list_filter = ['game', 'is_active']
inlines = [LineupPlayerInline]
inlines = [CsLineupPlayerInline]

def get_is_active(self, obj):
return obj.get_is_active()
Expand All @@ -194,7 +195,7 @@ class MatchAdmin(admin.ModelAdmin):
list_filter = ['lineup_a', 'lineup_b']
search_fields = ['lineup_b__team__name', 'lineup_b__team__name_long', 'tournament__name']
autocomplete_fields = ['lineup_a', 'lineup_b', 'tournament']
inlines = [MatchMapInline, ExternalLinkInline]
inlines = [CsMatchMapInline, ExternalLinkInline]
# replace "Save and add another" button with "Save as new" to use previous matches as template
# https://docs.djangoproject.com/en/5.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.save_as
save_as = True
Expand All @@ -210,7 +211,7 @@ class PlayerAdmin(admin.ModelAdmin):
list_editable = ['ingame_name', 'first_name', 'last_name']


class LineupPlayerAdmin(admin.ModelAdmin):
class CsLineupPlayerAdmin(admin.ModelAdmin):
list_display = ['player', 'role', 'lineup']
list_editable = ['role']
list_filter = ['role']
Expand Down Expand Up @@ -238,15 +239,14 @@ def save_global(modeladmin, request, queryset):


admin.site.register(models.Team, TeamAdmin)
admin.site.register(models.Lineup, LineupAdmin)
admin.site.register(models.LineupPlayer, LineupPlayerAdmin)
admin.site.register(models.CsLineup, LineupAdmin)
admin.site.register(models.CsLineupPlayer, CsLineupPlayerAdmin)
admin.site.register(models.ExternalLink, ExternalLinkAdmin)
admin.site.register(models.Map)
admin.site.register(models.Match, MatchAdmin)
admin.site.register(models.MatchMap, MatchMapAdmin)
admin.site.register(models.Player, PlayerAdmin)
admin.site.register(models.PlayerRole)
admin.site.register(models.Tournament, TournamentAdmin)
admin.site.register(models.CsMap)
admin.site.register(models.CsMatch, MatchAdmin)
admin.site.register(models.CsMatchMap, MatchMapAdmin)
admin.site.register(models.CsPlayer, PlayerAdmin)
admin.site.register(models.CsTournament, CsTournamentAdmin)
admin.site.register(models.Game, GameAdmin)
admin.site.register(models.StaticPage)

Expand Down
85 changes: 49 additions & 36 deletions csgomatches/drf_api/ser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,88 +3,101 @@
from django.apps import apps

from . import ser_objects
from csgomatches.models.cs_models import CSLineupPlayerRole

class CSGOTournamentSerializer(serializers.ModelSerializer):
class CsTournamentSerializer(serializers.ModelSerializer):
class Meta:
model = apps.get_model('csgomatches.Tournament')
model = apps.get_model('csgomatches.CsTournament')
fields = ['name', 'name_alt', 'name_hltv', 'name_99dmg', 'id']


class CSGOTeamSerializer(serializers.ModelSerializer):
class TeamSerializer(serializers.ModelSerializer):
class Meta:
model = apps.get_model('csgomatches.Team')
fields = ['name', 'name_long', 'name_alt', 'hltv_id', 'id']


class CSGOPlayerShortSerializer(serializers.ModelSerializer):
class CsPlayerShortSerializer(serializers.ModelSerializer):
class Meta:
model = apps.get_model('csgomatches.Player')
model = apps.get_model('csgomatches.CsPlayer')
fields = ['ingame_name',]

class CsLineupPlayerSerializer(serializers.ModelSerializer):
player = CsPlayerShortSerializer()
role = serializers.SerializerMethodField()

class CSGOPlayerRoleShortSerializer(serializers.ModelSerializer):
class Meta:
model = apps.get_model('csgomatches.PlayerRole')
fields = ['name',]
model = apps.get_model('csgomatches.CsLineupPlayer')
fields = ['player', 'role']

class CSGOLineupPlayerSerializer(serializers.ModelSerializer):
player = CSGOPlayerShortSerializer()
role = CSGOPlayerRoleShortSerializer()
def to_representation(self, instance):
representation = super().to_representation(instance)
# Map the enum value to a more human-readable string
representation['role'] = CSLineupPlayerRole(instance.role).name if instance.role else None
return representation

class Meta:
model = apps.get_model('csgomatches.LineupPlayer')
fields = ['player', 'role', ]
def to_internal_value(self, data):
# Convert string to enum value during deserialization
internal_value = super().to_internal_value(data)
role = data.get('role')

if role is not None:
try:
internal_value['role'] = CSLineupPlayerRole[role].value
except KeyError:
raise serializers.ValidationError(f"Invalid role: {role}")
return internal_value


class CSGOLineupSerializer(serializers.ModelSerializer):
team = CSGOTeamSerializer(read_only=True)
players = CSGOLineupPlayerSerializer(many=True, read_only=True, source='lineupplayer_set')
class CsLineupSerializer(serializers.ModelSerializer):
team = TeamSerializer(read_only=True)
players = CsLineupPlayerSerializer(many=True, read_only=True, source='lineupplayer_set')

class Meta:
model = apps.get_model('csgomatches.Lineup')
model = apps.get_model('csgomatches.CsLineup')
fields = ['team', 'team_logo_url', 'active_from', 'players', 'id']

class CSGOMapSerializer(serializers.ModelSerializer):
class CsMapSerializer(serializers.ModelSerializer):
class Meta:
model = apps.get_model('csgomatches.Map')
model = apps.get_model('csgomatches.CsMap')
fields = ['name', 'cs_name', 'id']

class CSGOMatchMapSerializer(serializers.ModelSerializer):
map_pick_of = CSGOLineupSerializer(read_only=True)
played_map = CSGOMapSerializer(read_only=True)
class CsMatchMapSerializer(serializers.ModelSerializer):
map_pick_of = CsLineupSerializer(read_only=True)
played = CsMapSerializer(read_only=True)

class Meta:
model = apps.get_model('csgomatches.MatchMap')
fields = ['rounds_won_team_a', 'rounds_won_team_b', 'starting_at', 'map_pick_of', 'played_map', 'id']
model = apps.get_model('csgomatches.CsMatchMap')
fields = ['rounds_won_team_a', 'rounds_won_team_b', 'starting_at', 'map_pick_of', 'map', 'id']


class CSGOMatchSerializer(serializers.ModelSerializer):
tournament = CSGOTournamentSerializer(read_only=True)
lineup_a = CSGOLineupSerializer(read_only=True)
lineup_b = CSGOLineupSerializer(read_only=True)
class CsMatchSerializer(serializers.ModelSerializer):
tournament = CsTournamentSerializer(read_only=True)
lineup_a = CsLineupSerializer(read_only=True)
lineup_b = CsLineupSerializer(read_only=True)
livescore_url = serializers.SerializerMethodField(read_only=True, source='get_livescore_url')
html_detail_url = serializers.SerializerMethodField(read_only=True, source='get_html_detail_url')
matchmaps = CSGOMatchMapSerializer(many=True, source='matchmap_set')
matchmaps = CsMatchMapSerializer(many=True, source='matchmap_set')

def get_livescore_url(self, obj):
if obj.hltv_match_id:
url = reverse('match_livescore-detail', kwargs={'pk': obj.hltv_match_id})
request = self.context.get('request')
return request.build_absolute_uri(url)
return request.build_absolute_uri(url) # type: ignore

def get_html_detail_url(self, obj):
url = obj.get_absolute_url()
request = self.context.get('request')
return request.build_absolute_uri(url)
return request.build_absolute_uri(url) # type: ignore

class Meta:
model = apps.get_model('csgomatches.Match')
model = apps.get_model('csgomatches.CsMatch')
fields = ['tournament', 'lineup_a', 'lineup_b', 'slug', 'bestof', 'first_map_at', 'cancelled', 'hltv_match_id', 'livescore_url', 'html_detail_url', 'matchmaps']


class CSGOMatchMapUpdateSerializer(serializers.ModelSerializer):
class CsMatchMapUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = apps.get_model('csgomatches.MatchMap')
model = apps.get_model('csgomatches.CsMatchMap')
fields = ['map_nr', 'rounds_won_team_a', 'rounds_won_team_b',]


Expand Down Expand Up @@ -117,7 +130,7 @@ def get_api_match_url(self, obj):
if csgo_match:
url = reverse('match_all-detail', kwargs={'pk': csgo_match.pk})
request = self.context.get('request')
return request.build_absolute_uri(url)
return request.build_absolute_uri(url) # type: ignore

def create(self, validated_data):
hltv_match_id = validated_data.get('hltv_match_id')
Expand Down
6 changes: 3 additions & 3 deletions csgomatches/drf_api/urls.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from rest_framework import routers, renderers
from . import views
from rest_framework import routers
from csgomatches.drf_api import views

router = routers.DefaultRouter()
router.APIRootView = views.CSGOAPIRootView
router.APIRootView = views.CsAPIRootView
router.register(r'team', viewset=views.TeamViewSet)
router.register(r'tournament', viewset=views.TournamentViewSet)
router.register(r'lineup', viewset=views.LineupViewSet)
Expand Down
Loading