Skip to content

Commit f4798d2

Browse files
author
Alexa
committed
Added changes from PR MagiCircles#25
1 parent 08a5856 commit f4798d2

File tree

1 file changed

+189
-46
lines changed

1 file changed

+189
-46
lines changed

majilove/models.py

Lines changed: 189 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# -*- coding: utf-8 -*-
22
from collections import OrderedDict
3+
from math import ceil
34
from django.utils.translation import ugettext_lazy as _, string_concat, get_language
4-
from django.core.validators import MaxValueValidator, MinValueValidator
55
from django.db import models
66
from django.conf import settings as django_settings
77
from magi.models import User, uploadItem
88
from magi.item_model import MagiModel, i_choices, getInfoFromChoices
9-
from magi.abstract_models import BaseAccount
9+
from magi.abstract_models import AccountAsOwnerModel, BaseAccount
1010
from magi.utils import templateVariables
1111

1212

@@ -131,6 +131,7 @@ class Photo(MagiModel):
131131

132132
# The square icon
133133
image = models.ImageField(_('Icon'), upload_to=uploadItem('photo'), null=True)
134+
134135
image_special_shot = models.ImageField(string_concat(_('Icon'), ' (', _('Special shot'), ')'), upload_to=uploadItem('photo/specialshot'), null=True)
135136

136137
# Full photo
@@ -149,7 +150,7 @@ class Photo(MagiModel):
149150

150151
message_text = models.TextField(string_concat(_('Message text'), ' (', _('Japanese') + ')'), max_length=500, null=True)
151152
message_translation = models.TextField(_('Message translation'), max_length=500, null=True)
152-
MESSAGE_TRANSLATIONs_CHOICES = ALL_ALT_LANGUAGES
153+
MESSAGE_TRANSLATIONS_CHOICES = ALL_ALT_LANGUAGES
153154
d_message_translations = models.TextField(_('Message translation'), null=True)
154155
@property
155156
def t_message_translation(self):
@@ -406,7 +407,6 @@ def japanese_skill(self):
406407
skill_percentage = models.FloatField('{skill_percentage}', null=True)
407408
skill_percentage_int = property(lambda _a: int(_a.skill_percentage))
408409

409-
410410
# Subskills
411411
SUB_SKILL_TYPES = OrderedDict([
412412
('full_combo', {
@@ -495,61 +495,204 @@ def __unicode__(self):
495495
return u''
496496

497497
############################################################
498-
# Songs
498+
# Collectible Photos
499499

500-
class Song(MagiModel):
501-
collection_name = 'song'
500+
class CollectiblePhoto(AccountAsOwnerModel):
501+
collection_name = 'collectiblephoto'
502502

503-
owner = models.ForeignKey(User, related_name='added_songs')
503+
account = models.ForeignKey(Account, verbose_name=_('Account'), related_name='photoscollectors')
504+
photo = models.ForeignKey(Photo, verbose_name=_('Photo'), related_name='collectedphotos')
505+
level = models.PositiveIntegerField(_('Level'), default=1)
506+
leader_bonus = models.PositiveIntegerField(_('Leader skill percentage'), null=True)
507+
skill_level = models.PositiveIntegerField(_('Skill level'), default=1)
504508

505-
name = models.CharField(string_concat(_('Title'), ' (', _('Translation'), ')'), max_length=100, null=True)
506-
japanese_name = models.CharField(_('Title'), max_length=100, null=True)
507-
NAMES_CHOICES = ALL_ALT_LANGUAGES
508-
d_names = models.TextField(_('Title'), null=True)
509509
@property
510-
def t_name(self):
511-
if get_language() == 'ja': return self.japanese_name
512-
return self.names.get(get_language(), self.name)
510+
def skill_percentage(self):
511+
return self.photo.skill_percentage + (self.skill_level - 1) * self.photo.skill_increment
512+
@property
513+
def skill_note_count(self):
514+
return self.photo.skill_note_count + (self.skill_level - 1) * self.photo.skill_increment
515+
516+
@property
517+
def skill(self):
518+
return self.photo.skill_template.format({
519+
k: getattr(self, k)
520+
for k in templateVariables(self.photo.skill_template)
521+
})
513522

514-
image = models.ImageField('Album cover', upload_to=uploadItem('song'), null=True)
523+
sub_skill_level = models.PositiveIntegerField(_('Sub skill level'), null=True)
524+
@property
525+
def sub_skill_amount(self):
526+
return self.photo.sub_skill_amount + (self.sub_skill_level - 1) * self.photo.sub_skill_increment
515527

516-
composer = models.CharField(_('Composer'), max_length=100, null=True)
517-
COMPOSERS_CHOICES = LANGUAGES_NEED_OWN_NAME
518-
d_composers = models.TextField(_('Composer'), null=True)
519-
lyricist = models.CharField(_('Lyricist'), max_length=100, null=True)
520-
LYRICISTS_CHOICES = LANGUAGES_NEED_OWN_NAME
521-
d_lyricists = models.TextField(_('Lyricist'), null=True)
522-
arranger = models.CharField(_('Arranger'), max_length=100, null=True)
523-
ARRANGERS_CHOICES = LANGUAGES_NEED_OWN_NAME
524-
d_arrangers = models.TextField(_('Arranger'), null=True)
528+
@property
529+
def sub_skill(self):
530+
_sub_skill_variables = {k: getattr(self.photo, k)
531+
for k in templateVariables(self.photo.sub_skill_template
532+
)}
533+
_sub_skill_variables['sub_skill_amount'] = self.sub_skill_amount
534+
return self.photo.sub_skill_template.format(**_sub_skill_variables)
525535

526-
singers = models.ManyToManyField(Idol, related_name="sung_songs", verbose_name=_('Singers'))
536+
rank = models.PositiveIntegerField(_('Rank'), default=1)
527537

528-
COLOR_CHOICES = Photo.COLOR_CHOICES
529-
i_color = models.PositiveIntegerField(_('Color'), choices=i_choices(COLOR_CHOICES))
538+
# TODO: moment based things are the same across, do I need an intermediate model for moment things?
530539

531-
DIFFICULTY_VALIDATORS = [
532-
MinValueValidator(1),
533-
MaxValueValidator(13),
540+
# percentage displayed on moments page for the card
541+
moments_unlocked = models.PositiveIntegerField(_('Percent of moments unlocked'), default = 0)
542+
# integer number of squares
543+
bonus_moment_squares_unlocked = models.PositiveIntegerField(_('Number of moment squares unlocked past 100%'), default = 0)
544+
@property
545+
def special_shot_unlocked(self):
546+
return self.moments_unlocked >= self.photo.special_shot_percentage
547+
548+
prefer_normal_shot = models.BooleanField(_('Prefer normal shot photo image'), default=False)
549+
550+
@property
551+
def image(self):
552+
return self.photo.image_special_shot if self.special_shot_unlocked and not self.prefer_normal_shot else self.photo.image
553+
554+
@property
555+
def art(self):
556+
return self.photo.art_special_shot if self.special_shot_unlocked and not self.prefer_normal_shot else self.photo.art
557+
558+
@property
559+
def final_leader_skill_percentage(self):
560+
if self.leader_bonus: return self.leader_bonus
561+
if self.photo.rarity is 'UR' and self.bonus_moment_squares_unlocked is 16: return 70
562+
_extra_squares = self.bonus_moment_squares_unlocked - 1
563+
if self.photo.rarity is 'UR': _extra_squares = (self.bonus_moment_squares_unlocked // 4) - 1
564+
if _extra_squares < 0: _extra_squares = 0
565+
return self.photo.leader_skill_percentage + (_extra_squares * 3)
566+
567+
@property
568+
def leader_skill(self):
569+
_leader_skill_variables = {
570+
k: getattr(self.photo, k)
571+
for k in templateVariables(Photo.LEADER_SKILL_INFO['template'])
572+
}
573+
_leader_skill_variables['leader_skill_percentage'] = self.final_leader_skill_percentage
574+
return Photo.LEADER_SKILL_INFO['template'].format(**_leader_skill_variables)
575+
576+
CROWN_OPTIONS = [150, 200]
577+
CROWN_TYPES = [
578+
'silver',
579+
'gold',
580+
'rainbow',
534581
]
582+
CROWN_TEMPLATE = '+{crown_amount} {crown_attribute}'
583+
SILVER_CROWN_AMOUNT_CHOICES = CROWN_OPTIONS
584+
i_silver_crown_amount = models.PositiveIntegerField(_('Silver crown bonus'), choices=i_choices(SILVER_CROWN_AMOUNT_CHOICES), null=True)
585+
SILVER_CROWN_ATTRIBUTE_CHOICES = Photo.LEADER_SKILL_STAT_CHOICES
586+
i_silver_crown_attribute = models.PositiveIntegerField(_('Silver crown attribute'), choices=i_choices(SILVER_CROWN_ATTRIBUTE_CHOICES), null=True)
587+
@property
588+
def silver_crown(self):
589+
if self.silver_crown_attribute is None: return None
590+
return CROWN_TEMPLATE.format(**{
591+
k: getattr(self, 'silver_{}'.format(k))
592+
for k in templateVariables(CROWN_TEMPLATE)
593+
})
535594

536-
easy_notes = models.PositiveIntegerField(string_concat(_('Easy'), ' - ', _('Notes')), null=True)
537-
easy_difficulty = models.PositiveIntegerField(string_concat(_('Easy'), ' - ', _('Difficulty')), validators=DIFFICULTY_VALIDATORS, null=True)
538-
normal_notes = models.PositiveIntegerField(string_concat(_('Normal'), ' - ', _('Notes')), null=True)
539-
normal_difficulty = models.PositiveIntegerField(string_concat(_('Normal'), ' - ', _('Difficulty')), validators=DIFFICULTY_VALIDATORS, null=True)
540-
hard_notes = models.PositiveIntegerField(string_concat(_('Hard'), ' - ', _('Notes')), null=True)
541-
hard_difficulty = models.PositiveIntegerField(string_concat(_('Hard'), ' - ', _('Difficulty')), validators=DIFFICULTY_VALIDATORS, null=True)
542-
pro_notes = models.PositiveIntegerField(string_concat(_('Pro'), ' - ', _('Notes')), null=True)
543-
pro_difficulty = models.PositiveIntegerField(string_concat(_('Pro'), ' - ', _('Difficulty')), validators=DIFFICULTY_VALIDATORS, null=True)
595+
GOLD_CROWN_AMOUNT_CHOICES = CROWN_OPTIONS
596+
i_gold_crown_amount = models.PositiveIntegerField(_('Gold crown bonus'), choices=i_choices(GOLD_CROWN_AMOUNT_CHOICES), null=True)
597+
GOLD_CROWN_ATTRIBUTE_CHOICES = Photo.LEADER_SKILL_STAT_CHOICES
598+
i_gold_crown_attribute = models.PositiveIntegerField(_('Gold crown attribute'), choices=i_choices(GOLD_CROWN_ATTRIBUTE_CHOICES), null=True)
599+
@property
600+
def gold_crown(self):
601+
if self.gold_crown_attribute is None: return None
602+
return CROWN_TEMPLATE.format(**{
603+
k: getattr(self, 'gold_{}'.format(k))
604+
for k in templateVariables(CROWN_TEMPLATE)
605+
})
606+
607+
RAINBOW_CROWN_AMOUNT_CHOICES = CROWN_OPTIONS
608+
i_rainbow_crown_amount = models.PositiveIntegerField(_('Rainbow crown bonus'), choices=i_choices(RAINBOW_CROWN_AMOUNT_CHOICES), null=True)
609+
RAINBOW_CROWN_ATTRIBUTE_CHOICES = Photo.LEADER_SKILL_STAT_CHOICES
610+
i_rainbow_crown_attribute = models.PositiveIntegerField(_('Rainbow crown attribute'), choices=i_choices(RAINBOW_CROWN_ATTRIBUTE_CHOICES), null=True)
611+
@property
612+
def rainbow_crown(self):
613+
if self.rainbow_crown_attribute is None: return None
614+
return CROWN_TEMPLATE.format(**{
615+
k: getattr(self, 'rainbow_{}'.format(k))
616+
for k in templateVariables(CROWN_TEMPLATE)
617+
})
618+
619+
@property
620+
def crown_dance_boost(self):
621+
return sum([getattr(self, '{}_crown_amount'.format(v)) for v in CROWN_TYPES
622+
if getattr(self, '{}_crown_attribute'.format(v)) is 'dance'])
623+
@property
624+
def crown_vocal_boost(self):
625+
return sum([getattr(self, '{}_crown_amount'.format(v)) for v in CROWN_TYPES
626+
if getattr(self, '{}_crown_attribute'.format(v)) is 'vocal'])
627+
@property
628+
def crown_charm_boost(self):
629+
return sum([getattr(self, '{}_crown_amount'.format(v)) for v in CROWN_TYPES
630+
if getattr(self, '{}_crown_attribute'.format(v)) is 'charm'])
631+
632+
custom_dance_stat = models.PositiveIntegerField(_('Dance'), null=True)
633+
custom_vocal_stat = models.PositiveIntegerField(_('Vocal'), null=True)
634+
custom_charm_stat = models.PositiveIntegerField(_('Charm'), null=True)
635+
636+
# pre moment stats
637+
@property
638+
def level_dance_stat(self):
639+
if self.level == 1: return self.photo.dance_min
640+
if self.level == self.photo.single_max_level: return self.photo.dance_single_copy_max
641+
if self.level == self.photo.max_max_level: return self.photo.dance_max_copy_max
642+
if self.level < self.photo.single_max_level:
643+
return self.photo.dance_min + ((self.level - 1) * self.photo.dance_single_copy_increment)
644+
return self.photo.dance_single_copy_max + ((self.level - self.photo.single_max_level) * self.photo.dance_combined_increment)
645+
@property
646+
def level_vocal_stat(self):
647+
if self.level == 1: return self.photo.vocal_min
648+
if self.level == self.photo.single_max_level: return self.photo.vocal_single_copy_max
649+
if self.level == self.photo.max_max_level: return self.photo.vocal_max_copy_max
650+
if self.level < self.photo.single_max_level:
651+
return self.photo.vocal_min + ((self.level - 1) * self.photo.vocal_single_copy_increment)
652+
return self.photo.vocal_single_copy_max + ((self.level - self.photo.single_max_level) * self.photo.vocal_combined_increment)
653+
@property
654+
def level_charm_stat(self):
655+
if self.level == 1: return self.photo.charm_min
656+
if self.level == self.photo.single_max_level: return self.photo.charm_single_copy_max
657+
if self.level == self.photo.max_max_level: return self.photo.charm_max_copy_max
658+
if self.level < self.photo.single_max_level:
659+
return self.photo.charm_min + ((self.level - 1) * self.photo.charm_single_copy_increment)
660+
return self.photo.charm_single_copy_max + ((self.level - self.photo.single_max_level) * self.photo.charm_combined_increment)
544661

545-
length = models.PositiveIntegerField(_('Length'), null=True)
662+
@property
663+
def moment_squares_unlocked(self):
664+
return ceil((self.moments_unlocked / 100) * self.photo.rarity_squares_in_moments) + (self.bonus_moment_squares_unlocked if self.photo.rarity is 'UR' else 0)
546665

547-
# just going to have unlock method for regular permanent songs for now
548-
unlock_chapter = models.CharField(_('Unlock Chapter'), max_length=100, null=True)
549-
UNLOCK_CHAPTERS_CHOICES = ALL_ALT_LANGUAGES
550-
d_unlock_chapters = models.TextField(_('Unlock Chapter'), null=True)
666+
# squares go +30 dance->vocal->charm->big square
667+
@property
668+
def moment_dance_bonus(self):
669+
return ceil(self.moment_squares_unlocked / 4) * 30
670+
@property
671+
def moment_vocal_bonus(self):
672+
return ((self.moment_squares_unlocked // 4) + (1 if (self.moment_squares_unlocked % 4) >= 2 else 0)) * 30
673+
@property
674+
def moment_charm_bonus(self):
675+
return ((self.moment_squares_unlocked // 4) + (1 if (self.moment_squares_unlocked % 4) >= 3 else 0)) * 30
551676

552-
#TODO: other unlock methods
677+
@property
678+
def display_dance(self):
679+
if self.custom_dance_stat: self.custom_dance_stat
680+
return self.level_dance_stat + self.moment_dance_bonus + self.crown_dance_boost
681+
@property
682+
def display_vocal(self):
683+
if self.custom_vocal_stat: self.custom_vocal_stat
684+
return self.level_vocal_stat + self.moment_vocal_bonus + self.crown_vocal_boost
685+
@property
686+
def display_charm(self):
687+
if self.custom_charm_stat: self.custom_charm_stat
688+
return self.level_charm_stat + self.moment_charm_bonus + self.crown_charm_boost
689+
690+
@property
691+
def total_stats(self):
692+
return self.display_dance + self.display_vocal + self.display_charm
553693

554694
def __unicode__(self):
555-
return unicode(self.t_name)
695+
if self.id:
696+
return unicode(self.photo)
697+
return super(CollectiblePhoto, self).__unicode__()
698+

0 commit comments

Comments
 (0)