Commit 68957fea187ef209cfcaa5d4a300e882f09190e8

Authored by Bartłomiej Nitoń
0 parents

Initial commit.

Showing 704 changed files with 200055 additions and 0 deletions

Too many changes to show.

To preserve performance only 28 of 704 files are displayed.

INSTALL 0 → 100644
  1 +++ a/INSTALL
  1 +Slowal installation guide:
  2 +To run Slowal you will need at least:
  3 + - python (tested on 2.7 version);
  4 + - django with django-registration (tested on version 0.7) and django-extensions packages;
  5 + - database system (tested on PostgreSQL 9.1);
  6 + - morphological analyser Morfeusz (http://sgjp.pl/morfeusz/).
  7 +
  8 + Slowal can be installed on production server as any other Django application. Comprehensive tutorial for setting Django on production server can be found at: http://bailey.st/blog/2012/05/02/ubuntu-django-postgresql-and-nginx-a-rock-solid-web-stack/. Tutorial can also be helpful for setting database for Slowal project.
  9 +
  10 +Installation:
  11 + 1) Change database_data.py file to get connection to yours database (see: http://bailey.st/blog/2012/05/02/ubuntu-django-postgresql-and-nginx-a-rock-solid-web-stack/ for hints).
  12 +When you are creating database it is important to make database coding 'utf8' and locale Polish.
  13 +In PostgreSQL such database would be created by command:
  14 +>>> createdb databaseName -E UTF8 -T template0 -l pl_PL.utf8
  15 + 2) If you want to run Slowal in the domain subfolder change SITE_PREFIX = '' value to other, for example SITE_PREFIX = '/Slowal'
  16 + 3) Create database table running:
  17 +>>> python manage.py syncdb
  18 +command in the main folder of project. Remember to create superuser it will help you in managing database and give access to all Slowal functionalities.
  19 + 4) Fill database with initial values running:
  20 +>>> python manage.py import_models
  21 +command in the main folder of project.
  22 + 5) Create default user groups running:
  23 +>>> python manage.py create_groups.py
  24 +command in the main folder of project.
  25 + 6) Slowal is ready to run.
  26 +
  27 +Slowal was tested on Safari, Opera, Firefox and Chrome web browsers. Working on Internet Explorer compatibility is still in progress
... ...
LICENSE 0 → 100644
  1 +++ a/LICENSE
  1 +Copyright (c) 2012, Bartłomiej Nitoń
  2 +All rights reserved.
  3 +
  4 +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
  5 +
  6 + Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  7 + Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  8 +
  9 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
... ...
__init__.py 0 → 100644
  1 +++ a/__init__.py
... ...
accounts/__init__.py 0 → 100644
  1 +++ a/accounts/__init__.py
... ...
accounts/admin.py 0 → 100644
  1 +++ a/accounts/admin.py
  1 +#-*- coding:utf-8 -*-
  2 +
  3 +#Copyright (c) 2012, Bartłomiej Nitoń
  4 +#All rights reserved.
  5 +
  6 +#Redistribution and use in source and binary forms, with or without modification, are permitted provided
  7 +#that the following conditions are met:
  8 +
  9 +# Redistributions of source code must retain the above copyright notice, this list of conditions and
  10 +# the following disclaimer.
  11 +# Redistributions in binary form must reproduce the above copyright notice, this list of conditions
  12 +# and the following disclaimer in the documentation and/or other materials provided with the distribution.
  13 +
  14 +#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
  15 +#WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  16 +#PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  17 +#ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  18 +#TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  19 +#HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  20 +#NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  21 +#POSSIBILITY OF SUCH DAMAGE.
  22 +
  23 +from django.contrib import admin
  24 +from django.contrib.sessions.models import Session
  25 +
  26 +from models import AnonymousUserProfile, RealizedLemma, GroupSettings, \
  27 + RealizedPhraseology, RealizedPhraseologyBinding, \
  28 + RealizedSemantics, UserSettings, UserStats
  29 +
  30 +class RealizedLemmaAdmin(admin.ModelAdmin):
  31 + search_fields = ('lemma__entry',)
  32 + list_filter = ('status', 'paid', 'lemma__vocabulary', 'bonus', 'counted',)
  33 +
  34 +class RealizedPhraseologyAdmin(admin.ModelAdmin):
  35 + search_fields = ('lemma__entry',)
  36 + list_filter = ('status', 'paid', 'lemma__vocabulary', 'bonus', 'counted',)
  37 +
  38 +class RealizedSemanticsAdmin(admin.ModelAdmin):
  39 + search_fields = ('entry__name',)
  40 + list_filter = ('status', 'bonus', )
  41 +
  42 +class UserStatsAdmin(admin.ModelAdmin):
  43 + exclude = ('lemma_real_history', 'phraseology_real_history',
  44 + 'bind_phraseology_frames_history')
  45 +
  46 +admin.site.register(UserSettings)
  47 +admin.site.register(UserStats, UserStatsAdmin)
  48 +admin.site.register(RealizedLemma, RealizedLemmaAdmin)
  49 +admin.site.register(RealizedPhraseology, RealizedPhraseologyAdmin)
  50 +admin.site.register(RealizedSemantics, RealizedSemanticsAdmin)
  51 +admin.site.register(GroupSettings)
  52 +admin.site.register(RealizedPhraseologyBinding)
  53 +admin.site.register(AnonymousUserProfile)
  54 +
  55 +admin.site.register(Session)
... ...
accounts/forms.py 0 → 100644
  1 +++ a/accounts/forms.py
  1 +#-*- coding:utf-8 -*-
  2 +
  3 +#Copyright (c) 2012, Bartłomiej Nitoń
  4 +#All rights reserved.
  5 +
  6 +#Redistribution and use in source and binary forms, with or without modification, are permitted provided
  7 +#that the following conditions are met:
  8 +
  9 +# Redistributions of source code must retain the above copyright notice, this list of conditions and
  10 +# the following disclaimer.
  11 +# Redistributions in binary form must reproduce the above copyright notice, this list of conditions
  12 +# and the following disclaimer in the documentation and/or other materials provided with the distribution.
  13 +
  14 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
  15 +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  16 +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  17 +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  18 +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  19 +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  20 +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  21 +# POSSIBILITY OF SUCH DAMAGE.
  22 +
  23 +from django.forms import ModelForm
  24 +from accounts.models import UserSettings
  25 +
  26 +class SettingsForm(ModelForm):
  27 + class Meta:
  28 + model = UserSettings
  29 + fields = ['incremental_search', 'notes_per_page']
... ...
accounts/models.py 0 → 100644
  1 +++ a/accounts/models.py
  1 +#-*- coding:utf-8 -*-
  2 +
  3 +#Copyright (c) 2012, Bartłomiej Nitoń
  4 +#All rights reserved.
  5 +
  6 +#Redistribution and use in source and binary forms, with or without modification, are permitted provided
  7 +#that the following conditions are met:
  8 +
  9 +# Redistributions of source code must retain the above copyright notice, this list of conditions and
  10 +# the following disclaimer.
  11 +# Redistributions in binary form must reproduce the above copyright notice, this list of conditions
  12 +# and the following disclaimer in the documentation and/or other materials provided with the distribution.
  13 +
  14 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
  15 +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  16 +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  17 +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  18 +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  19 +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  20 +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  21 +# POSSIBILITY OF SUCH DAMAGE.
  22 +
  23 +from django.db.models import *
  24 +from django.contrib.auth.models import User, Group
  25 +from django.core.validators import MinValueValidator, MaxValueValidator
  26 +
  27 +from dictionary.models import Entry, Frame, Message, Lemma, Lemma_Status, Vocabulary
  28 +from semantics.models import SemanticFrame
  29 +
  30 +MANAGER_GROUPS = (u'Gość', u'Leksykograf', u'Superleksykograf', u'Administrator', u'Gość+', u'Frazeolog')
  31 +
  32 +def manager_groups():
  33 + return Group.objects.filter(name__in=MANAGER_GROUPS)
  34 +
  35 +class UserStats(Model):
  36 + user = OneToOneField(User, related_name='user_stats')
  37 + # oplaty za prace leksykograficzne
  38 + lemma_real_history = ManyToManyField('RealizedLemma', db_table='zrealizowane_hasla',
  39 + blank=True, null=True, related_name='user_stats')
  40 + # oplaty za prace leksykograficzne
  41 + phraseology_real_history = ManyToManyField('RealizedPhraseology', db_table='prace_frazeologiczne',
  42 + blank=True, null=True, related_name='user_stats')
  43 + # oplaty za prace leksykograficzne
  44 + bind_phraseology_frames_history = ManyToManyField('RealizedPhraseologyBinding', db_table='powiazania_frazeologiczne',
  45 + blank=True, null=True, related_name='user_stats')
  46 + # !NOWE! oplaty za prace semantyczne
  47 + semantics_real_history = ManyToManyField('RealizedSemantics', db_table='prace_semantyczne',
  48 + blank=True, null=True, related_name='user_stats')
  49 + # kwota uiszczona
  50 + paid_cash = FloatField(db_column='kwota_uiszczona', default = 0.0)
  51 +
  52 + def __unicode__(self):
  53 + return '%s' % (self.user)
  54 +
  55 + def made_phraseologic_empty_entries_count(self):
  56 + return self.phraseology_real_history.filter(status__type__sym_name='ready_f',
  57 + paid=False,
  58 + new_frames=0,
  59 + reused_frames=0).count()
  60 +
  61 + def checked_phraseologic_empty_entries_count(self):
  62 + return self.phraseology_real_history.filter(status__type__sym_name='checked_f',
  63 + paid=False,
  64 + corr_frames=0,
  65 + ncorr_frames=0,
  66 + bonus=False).count()
  67 +
  68 +def can_modify_phraseology_only(user, phraseologic):
  69 + return phraseologic and user.has_perm('dictionary.add_phraseologic_frames')
  70 +
  71 +class RealizedLemma(Model):
  72 + """Model representing realized and confirmed frames by user."""
  73 + # wykonane haslo
  74 + lemma = ForeignKey(Lemma, db_column='wykonane_haslo', related_name='realized_lemmas')
  75 + # wynagrodzenie za haslo
  76 + cash = FloatField(db_column='wynagrodzenie', default = 0.0)
  77 + # czy wykonanie hasla zostalo juz wynagrodzone
  78 + paid = BooleanField(db_column='oplacono', default=False)
  79 + # ta oplata zostala juz podliczona na pewnym etapie i nie nalezy zmieniac jej wartosci
  80 + counted = BooleanField(db_column='przeliczono', default=False)
  81 + # czy oplata jest bonusem dla leksykografa
  82 + bonus = BooleanField(db_column='bonus', default=False)
  83 + #wlasciwie wykonane schematy (wypelniane dla leksykografa)
  84 + prop_frames = PositiveIntegerField(db_column='poprawne_ramki',
  85 + default = 0)
  86 + # niewlasciwie wykonane schematy (wypelniane dla leksykografa)
  87 + wrong_frames = PositiveIntegerField(db_column='niepoprawne_ramki',
  88 + default = 0)
  89 + # poprawione schematy (wypelniane dla superleksykografa)
  90 + corr_frames = PositiveIntegerField(db_column='poprawione_ramki',
  91 + default = 0)
  92 + # poprawione schematy (wypelniane dla superleksykografa)
  93 + made_frames = PositiveIntegerField(db_column='wykonane_ramki',
  94 + default = 0)
  95 + # schematy niepoprawiane (wypelniane dla supeleksykografa)
  96 + ncorr_frames = PositiveIntegerField(db_column='niepoprawione_ramki',
  97 + default = 0)
  98 + date = DateTimeField(auto_now_add=True, db_column='data_zmiany')
  99 + # statusu hasla za przejscie do ktorego otrzymano oplate
  100 + status = ForeignKey(Lemma_Status, related_name='realized_lemmas',
  101 + blank=True, null=True)
  102 +
  103 + def __unicode__(self):
  104 + return '%s: %f' % (self.lemma.entry, self.cash)
  105 +
  106 +class RealizedPhraseology(Model):
  107 + """Model representing realized phraseology work."""
  108 + # wykonane haslo
  109 + lemma = ForeignKey(Lemma, db_column='haslo', related_name='realized_phraseology')
  110 + # wynagrodzenie za haslo
  111 + cash = FloatField(db_column='wynagrodzenie', default = 0.0)
  112 + # czy praca zostala juz oplacona
  113 + paid = BooleanField(db_column='oplacono', default=False)
  114 + # ta oplata zostala juz podliczona na pewnym etapie i nie nalezy zmieniac jej wartosci
  115 + counted = BooleanField(db_column='przeliczono', default=False)
  116 + # czy oplata jest bonusem
  117 + bonus = BooleanField(db_column='bonus', default=False)
  118 + # stworzone nowe schematy frazeologiczne
  119 + new_frames = PositiveIntegerField(db_column='nowe_ramki',
  120 + default = 0)
  121 + # schematy pochodzace z podpowiedzi lub juz wczesniej istniejace dla danego lematu
  122 + reused_frames = PositiveIntegerField(db_column='ponownie_uzyte_ramki',
  123 + default = 0)
  124 + #wlasciwie wykonane schematy (wypelniane dla frazeologa)
  125 + prop_frames = PositiveIntegerField(db_column='poprawne_ramki',
  126 + default = 0)
  127 + # niewlasciwie wykonane schematy (wypelniane dla frazeologa)
  128 + wrong_frames = PositiveIntegerField(db_column='niepoprawne_ramki',
  129 + default = 0)
  130 + # poprawione schematy (wypelniane dla superfrazeologa)
  131 + corr_frames = PositiveIntegerField(db_column='poprawione_ramki',
  132 + default = 0)
  133 + # schematy niepoprawiane (wypelniane dla superfrazeologa)
  134 + ncorr_frames = PositiveIntegerField(db_column='niepoprawione_ramki',
  135 + default = 0)
  136 + # data podliczenia pracy
  137 + date = DateTimeField(auto_now_add=True, db_column='data_zmiany')
  138 + # statusu hasla za przejscie do ktorego otrzymano oplate
  139 + status = ForeignKey(Lemma_Status, related_name='realized_phraseology',
  140 + blank=True, null=True)
  141 +
  142 + def __unicode__(self):
  143 + return '%s: %f' % (self.lemma.entry, self.cash)
  144 +
  145 +class RealizedPhraseologyBinding(Model):
  146 + """Model representing realized phraseology work."""
  147 + # wykonane haslo
  148 + main_entry = ForeignKey(Entry, db_column='glowne_haslo',
  149 + related_name='realized_phraseology_bindings__main')
  150 + phraseologic_frame = ForeignKey(Frame, db_column='ramka_frazeologiczna',
  151 + related_name='realized_phraseology_bindings__binded')
  152 + binded_entry = ForeignKey(Entry, db_column='przypisane_haslo',
  153 + related_name='realized_phraseology_bindings')
  154 + cash = FloatField(db_column='wynagrodzenie', default = 0.0)
  155 + # czy praca zostala juz oplacona
  156 + paid = BooleanField(db_column='oplacono', default=False)
  157 + # ta oplata zostala juz podliczona na pewnym etapie i nie nalezy zmieniac jej wartosci
  158 + counted = BooleanField(db_column='przeliczono', default=False)
  159 + # data podliczenia pracy
  160 + date = DateTimeField(auto_now_add=True, db_column='data_zmiany')
  161 +
  162 + def __unicode__(self):
  163 + return u'%s: %f' % (self.phraseologic_frame, self.cash)
  164 +
  165 +class UserSettings(Model):
  166 + user = OneToOneField(User, related_name='user_settings')
  167 + incremental_search = BooleanField(
  168 + default=False,
  169 + verbose_name=u'wyszukiwanie przyrostowe',
  170 + help_text=u'Wyszukiwanie odbywa się automatycznie w miarę wpisywania '
  171 + u'szukanego hasła. Sugerujemy wyłączenie w wypadku wolnego '
  172 + u'połączenia internetowego.')
  173 + filter_search = BooleanField(
  174 + default=True,
  175 + verbose_name=u'wyszukiwanie przez filtrowanie',
  176 + help_text=u'Wyszukiwanie powoduje zawężenie listy haseł do pasujących '
  177 + u'do zapytania.')
  178 + notes_per_page = PositiveSmallIntegerField(default=40,
  179 + db_column='wiadomosci_na_strone',
  180 + verbose_name=u'Notatki na stronę',
  181 + help_text=u'Liczba notatek na stronę w skrzynce odbiorczej użytkownika.',
  182 + validators=[
  183 + MaxValueValidator(100),
  184 + MinValueValidator(10)]
  185 + )
  186 +
  187 + def has_new_messages(self):
  188 + lemmas_new_msg = self.user.lemmas.filter(messages__new=True).filter(messages__private=False)
  189 + if len(lemmas_new_msg) > 0:
  190 + return True;
  191 + return False;
  192 +
  193 + def new_notes_number(self):
  194 + new_notes = Message.objects.filter(recipient=self.user, private=False, new=True)
  195 + return len(new_notes)
  196 +
  197 + def change_all_lemmas(self):
  198 + return self.user.has_perm('dictionary.change_all_lemmas')
  199 +
  200 + def view_lemma(self):
  201 + return self.user.has_perm('dictionary.view_lemma')
  202 +
  203 + def view_realizations(self):
  204 + return self.user.has_perm('dictionary.view_realizations')
  205 +
  206 + def view_notes(self):
  207 + return self.user.has_perm('dictionary.view_notes')
  208 +
  209 + def add_notes(self):
  210 + return self.user.has_perm('dictionary.add_notes')
  211 +
  212 + def change_lemmas(self):
  213 + return self.user.has_perm('dictionary.change_lemmas')
  214 +
  215 + def change_lemma_status(self):
  216 + return self.user.has_perm('dictionary.change_lemma_status')
  217 +
  218 + def manages_vocabulary(self):
  219 + return self.user.has_perm('dictionary.manage_vocabulary')
  220 +
  221 + def download_vocabulary(self):
  222 + return self.user.has_perm('dictionary.download_vocabulary')
  223 +
  224 + def view_vocab_stats(self):
  225 + return self.user.has_perm('dictionary.view_vocab_stats')
  226 +
  227 + def edit_semantic_frames(self):
  228 + return self.user.has_perm('semantics.edit_frames')
  229 +
  230 + class Meta:
  231 + permissions = (
  232 + ('create_admin', u'Może nadawać dowolne role'),
  233 + )
  234 +
  235 +class GroupSettings(Model):
  236 + """Group settings model."""
  237 + group = OneToOneField(Group, related_name='group_settings')
  238 + abort_statuses = ManyToManyField(Lemma_Status, blank=True,
  239 + related_name='group_settings_abort')
  240 + next_statuses = ManyToManyField(Lemma_Status, blank=True,
  241 + related_name='group_settings_next')
  242 + active_statuses = ManyToManyField(Lemma_Status, blank=True,
  243 + related_name='group_settings_active')
  244 + priority = PositiveIntegerField(db_column='priorytet')
  245 +
  246 + def __unicode__(self):
  247 + return '%s' % self.group.name
  248 +
  249 +class AnonymousUserProfile(Model):
  250 + """Anonymous user settings."""
  251 + user_template = ForeignKey(User, db_column='szablon_uzytkownika',
  252 + related_name='anonymous_user_settings')
  253 + selected = BooleanField(db_column='wybrana', default=False)
  254 + visible_statuses = ManyToManyField(Lemma_Status, blank=True,
  255 + related_name='anonymous_user_profiles')
  256 +
  257 + def visible_vocabularies(self):
  258 + if self.user_template.has_perm('dictionary.view_all_lemmas'):
  259 + return Vocabulary.objects.all()
  260 + else:
  261 + return self.user_template.visible_vocabularies.all()
  262 +
  263 + def __unicode__(self):
  264 + return unicode(self.user_template)
  265 +
  266 +def get_anon_user():
  267 + return AnonymousUserProfile.objects.get(selected=True).user_template
  268 +
  269 +def get_anon_profile():
  270 + return AnonymousUserProfile.objects.get(selected=True)
  271 +
  272 +def filtering_mode(user):
  273 + return user.usersettings.filter_search
  274 +
  275 +# !NOWE!
  276 +class RealizedSemantics(Model):
  277 + """Model representing realized semantic work."""
  278 + # wykonane haslo
  279 + entry = ForeignKey(Entry, db_column='haslo',
  280 + related_name='realized_semantics')
  281 + # ramy semantyczne w momencie zapisu pracy
  282 + frames = ManyToManyField(SemanticFrame, db_table='ramy_semantyczne',
  283 + blank=True, null=True, related_name='realized_semantics')
  284 + # wynagrodzenie za haslo
  285 + cash = FloatField(db_column='wynagrodzenie', default=0.0)
  286 + # czy oplata jest bonusem dla semantyka
  287 + bonus = BooleanField(db_column='bonus', default=False)
  288 + # wlasciwie wykonane ramki (wypelniane dla semantyka)
  289 + prop_frames = PositiveIntegerField(db_column='poprawne_ramki',
  290 + default=0)
  291 + # niewlasciwie wykonane ramki (wypelniane dla semantyka)
  292 + wrong_frames = PositiveIntegerField(db_column='niepoprawne_ramki',
  293 + default=0)
  294 + # wykonane ramki (wypelniane dla semantyka)
  295 + made_frames = PositiveIntegerField(db_column='wykonane_ramki',
  296 + default=0)
  297 + # poprawione ramki (wypelniane dla supersemantyka)
  298 + corr_frames = PositiveIntegerField(db_column='poprawione_ramki',
  299 + default=0)
  300 + # ramki niepoprawiane (wypelniane dla supersemantyka)
  301 + ncorr_frames = PositiveIntegerField(db_column='niepoprawione_ramki',
  302 + default=0)
  303 + date = DateTimeField(auto_now_add=True, db_column='data_zmiany')
  304 + # statusu hasla za przejscie do ktorego otrzymano oplate
  305 + status = ForeignKey(Lemma_Status, related_name='realized_semantics',
  306 + blank=True, null=True)
  307 +
  308 + def __unicode__(self):
  309 + return '%s: %f' % (self.entry.name, self.cash)
... ...
accounts/templates/registration/login.html 0 → 100644
  1 +++ a/accounts/templates/registration/login.html
  1 +{% extends "base.html" %}
  2 +{% load i18n %}
  3 +{% load url from future %}
  4 +
  5 +{% block content %}
  6 +{% if form.errors and not form.non_field_errors and not form.this_is_the_login_form.errors %}
  7 +<p class="errornote">
  8 +{% blocktrans count form.errors.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
  9 +</p>
  10 +{% endif %}
  11 +
  12 +{% if form.non_field_errors or form.this_is_the_login_form.errors %}
  13 +{% for error in form.non_field_errors|add:form.this_is_the_login_form.errors %}
  14 +<p class="errornote">
  15 + {{ error }}
  16 +</p>
  17 +{% endfor %}
  18 +{% endif %}
  19 +
  20 +<div id="content-main">
  21 +<form action="" method="post" id="login-form">{% csrf_token %}
  22 + {{ form.as_p }}
  23 + <div class="submit-row">
  24 + <label>&nbsp;</label><input type="submit" value="{% trans 'Log in' %}" />
  25 + </div>
  26 +</form>
  27 +
  28 +<script type="text/javascript">
  29 +document.getElementById('id_username').focus()
  30 +</script>
  31 +</div>
  32 +{% endblock %}
... ...
accounts/templates/registration/logout.html 0 → 100644
  1 +++ a/accounts/templates/registration/logout.html
  1 +{% extends "base.html" %}
  2 +{% load i18n %}
  3 +{% load url from future %}
  4 +
  5 +{% block content %}
  6 +
  7 +<p>{% trans "Thanks for spending some quality time with the Web site today." %}</p>
  8 +
  9 +<p><a href="{% url 'auth_login' %}">{% trans 'Log in again' %}</a></p>
  10 +
  11 +{% endblock %}
... ...
accounts/templates/registration/password_change_done.html 0 → 100644
  1 +++ a/accounts/templates/registration/password_change_done.html
  1 +{% extends "base.html" %}
  2 +{% load i18n %}
  3 +{% load url from future %}
  4 +
  5 +{% block userlinks %}{% trans 'Change password' %} / <a href="{% url 'auth_logout' %}">{% trans 'Log out' %}</a>{% endblock %}
  6 +
  7 +{% block title %}{% trans 'Password change successful' %}{% endblock %}
  8 +
  9 +{% block content %}
  10 +
  11 +<h1>{% trans 'Password change successful' %}</h1>
  12 +
  13 +<p>{% trans 'Your password was changed.' %}</p>
  14 +
  15 +{% endblock %}
... ...
accounts/templates/registration/password_change_form.html 0 → 100644
  1 +++ a/accounts/templates/registration/password_change_form.html
  1 +{% extends "base.html" %}
  2 +{% load i18n %}
  3 +{% load url from future %}
  4 +{% block userlinks %}{% trans 'Change password' %} / <a href="{% url 'auth_logout' %}">{% trans 'Log out' %}</a>{% endblock %}
  5 +
  6 +{% block title %}{% trans 'Password change' %}{% endblock %}
  7 +
  8 +{% block content %}<div id="content-main">
  9 +
  10 +<form action="" method="post">{% csrf_token %}
  11 +<div>
  12 +{% if form.errors %}
  13 + <p class="errornote">
  14 + {% blocktrans count form.errors.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
  15 + </p>
  16 +{% endif %}
  17 +
  18 +<h1>{% trans 'Password change' %}</h1>
  19 +
  20 +<p>{% trans "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." %}</p>
  21 +
  22 +<fieldset class="module aligned wide">
  23 +
  24 +<div class="form-row">
  25 + {{ form.old_password.errors }}
  26 + <label for="id_old_password" class="required">{% trans 'Old password' %}:</label>{{ form.old_password }}
  27 +</div>
  28 +
  29 +<div class="form-row">
  30 + {{ form.new_password1.errors }}
  31 + <label for="id_new_password1" class="required">{% trans 'New password' %}:</label>{{ form.new_password1 }}
  32 +</div>
  33 +
  34 +<div class="form-row">
  35 +{{ form.new_password2.errors }}
  36 + <label for="id_new_password2" class="required">{% trans 'Password (again)' %}:</label>{{ form.new_password2 }}
  37 +</div>
  38 +
  39 +</fieldset>
  40 +
  41 +<div class="submit-row">
  42 + <input type="submit" value="{% trans 'Change my password' %}" class="default" />
  43 +</div>
  44 +
  45 +<script type="text/javascript">document.getElementById("id_old_password").focus();</script>
  46 +</div>
  47 +</form></div>
  48 +
  49 +{% endblock %}
... ...
accounts/templates/settings.html 0 → 100644
  1 +++ a/accounts/templates/settings.html
  1 +<!--
  2 +Copyright (c) 2012, Bartłomiej Nitoń
  3 +All rights reserved.
  4 +
  5 +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
  6 +
  7 + Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  8 + Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  9 +
  10 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  11 +-->
  12 +
  13 +{% extends "base.html" %}
  14 +{% load url from future %}
  15 +
  16 +{% block title %}Ustawienia{% endblock %}
  17 +
  18 +{% block content %}
  19 +<h1>Ustawienia użytkownika</h1>
  20 +<form method="post" action="">
  21 + {{ form.as_p }}
  22 + {% csrf_token %}
  23 + <input type="hidden" name="next" value="{{ next }}"/>
  24 + <button type="submit">
  25 + Zapisz
  26 + </button>
  27 +</form>
  28 +<p>
  29 + <a href="{% url 'auth_password_change' %}">Zmiana hasła</a>
  30 +</p>
  31 +{% endblock %}
... ...
accounts/tests.py 0 → 100644
  1 +++ a/accounts/tests.py
  1 +"""
  2 +This file demonstrates writing tests using the unittest module. These will pass
  3 +when you run "manage.py test".
  4 +
  5 +Replace this with more appropriate tests for your application.
  6 +"""
  7 +
  8 +from django.test import TestCase
  9 +
  10 +
  11 +class SimpleTest(TestCase):
  12 + def test_basic_addition(self):
  13 + """
  14 + Tests that 1 + 1 always equals 2.
  15 + """
  16 + self.assertEqual(1 + 1, 2)
... ...
accounts/views.py 0 → 100644
  1 +++ a/accounts/views.py
  1 +#-*- coding:utf-8 -*-
  2 +
  3 +#Copyright (c) 2012, Bartłomiej Nitoń
  4 +#All rights reserved.
  5 +
  6 +#Redistribution and use in source and binary forms, with or without modification, are permitted provided
  7 +#that the following conditions are met:
  8 +
  9 +# Redistributions of source code must retain the above copyright notice, this list of conditions and
  10 +# the following disclaimer.
  11 +# Redistributions in binary form must reproduce the above copyright notice, this list of conditions
  12 +# and the following disclaimer in the documentation and/or other materials provided with the distribution.
  13 +
  14 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
  15 +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  16 +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  17 +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  18 +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  19 +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  20 +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  21 +# POSSIBILITY OF SUCH DAMAGE.
  22 +
  23 +from django.http import HttpResponseRedirect
  24 +from django.contrib.auth.decorators import login_required
  25 +from common.decorators import render
  26 +from accounts.forms import SettingsForm
  27 +from accounts.models import UserSettings
  28 +
  29 +@login_required
  30 +@render()
  31 +def settings(request):
  32 + user_settings, created = UserSettings.objects.get_or_create(user=request.user)
  33 + if request.method == 'POST':
  34 + form = SettingsForm(data=request.POST, instance=user_settings)
  35 + if form.is_valid():
  36 + form.save()
  37 + return HttpResponseRedirect(request.POST['next'])
  38 + else:
  39 + form = SettingsForm(instance=user_settings)
  40 + return {'form': form, 'next': request.META.get('HTTP_REFERER', '')}
  41 +
... ...
common/__init__.py 0 → 100644
  1 +++ a/common/__init__.py
... ...
common/context_processors.py 0 → 100644
  1 +++ a/common/context_processors.py
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +def error_proc(request):
  4 + if request.session.get('error', ''):
  5 + error = request.session.pop('error')
  6 + return {'error': error}
  7 + else:
  8 + return {}
  9 +
  10 +def message_proc(request):
  11 + if request.session.get('message', ''):
  12 + message = request.session.pop('message')
  13 + return {'alert_message': message}
  14 + else:
  15 + return {}
... ...
common/decorators.py 0 → 100644
  1 +++ a/common/decorators.py
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +from functools import wraps
  4 +from inspect import getargspec
  5 +from django.http import HttpResponse
  6 +from django.utils.simplejson import loads as json_decode, dumps as json_encode
  7 +from django.utils.functional import curry
  8 +from django.conf import settings
  9 +from django.shortcuts import render_to_response
  10 +from django.template import RequestContext, generic_tag_compiler, Node
  11 +from django.template import TemplateSyntaxError, Variable
  12 +from common.util import stringify_keys
  13 +from django.db import transaction
  14 +
  15 +class AjaxError(Exception):
  16 + pass
  17 +
  18 +def json_decode_fallback(value):
  19 + try:
  20 + return json_decode(value)
  21 + except ValueError:
  22 + return value
  23 +
  24 +def ajax(login_required=False, method=None, encode_result=True):
  25 + def decorator(fun):
  26 + @wraps(fun)
  27 + def ajax_view(request):
  28 + kwargs = {}
  29 + request_params = None
  30 + if method == 'post':
  31 + request_params = request.POST
  32 + elif method == 'get':
  33 + request_params = request.GET
  34 + fun_params, xx, fun_kwargs, xxxx = getargspec(fun)
  35 + if request_params:
  36 + request_params = dict((key, json_decode_fallback(value))
  37 + for key, value in request_params.iteritems()
  38 + if fun_kwargs or key in fun_params)
  39 + kwargs.update(stringify_keys(request_params))
  40 + res = None
  41 + if login_required and not request.user.is_authenticated():
  42 + res = {'result': 'logout'}
  43 + if not res:
  44 + try:
  45 + res = fun(request, **kwargs)
  46 + except AjaxError as e:
  47 + res = {'result': e.args[0]}
  48 + transaction.rollback()
  49 + if encode_result:
  50 + if 'result' not in res:
  51 + res['result'] = 'ok'
  52 + return HttpResponse(json_encode(res), mimetype='application/json')
  53 + else:
  54 + return res
  55 + return ajax_view
  56 + return decorator
  57 +
  58 +def render(template=None, mimetype=None):
  59 + mimetype = mimetype or settings.DEFAULT_CONTENT_TYPE
  60 + template1 = template
  61 + def decorator(func):
  62 + template = template1 # no cóż...
  63 + if not template:
  64 + template = func.__name__ + '.html'
  65 + @wraps(func)
  66 + def renderer(request, *args, **kw):
  67 + output = func(request, *args, **kw)
  68 + if isinstance(output, (list, tuple)):
  69 + return render_to_response(output[1], output[0],
  70 + RequestContext(request), mimetype=mimetype)
  71 + elif isinstance(output, dict):
  72 + return render_to_response(template, output,
  73 + RequestContext(request), mimetype=mimetype)
  74 + return output
  75 + return renderer
  76 + return decorator
  77 +
  78 +def simple_tag(register, takes_context=False):
  79 + def decorator(func):
  80 + params, xx, xxx, defaults = getargspec(func)
  81 + if takes_context:
  82 + if params[0] == 'context':
  83 + params = params[1:]
  84 + else:
  85 + raise TemplateSyntaxError("Any tag function decorated with takes_context=True must have a first argument of 'context'")
  86 +
  87 + class SimpleNode(Node):
  88 + def __init__(self, vars_to_resolve):
  89 + self.vars_to_resolve = map(Variable, vars_to_resolve)
  90 +
  91 + def render(self, context):
  92 + resolved_vars = [var.resolve(context) for var in self.vars_to_resolve]
  93 + if takes_context:
  94 + args = [context] + resolved_vars
  95 + else:
  96 + args = resolved_vars
  97 + try:
  98 + return func(*args)
  99 + except Exception as e:
  100 + raise
  101 + return type(e).__name__+': '+str(e)
  102 +
  103 + compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode)
  104 + compile_func.__doc__ = func.__doc__
  105 + register.tag(getattr(func, "_decorated_function", func).__name__, compile_func)
  106 + return func
  107 + return decorator
... ...
common/js_to_obj.py 0 → 100644
  1 +++ a/common/js_to_obj.py
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +#Copyright (c) 2014, Bartłomiej Nitoń
  4 +#All rights reserved.
  5 +
  6 +#Redistribution and use in source and binary forms, with or without modification, are permitted provided
  7 +#that the following conditions are met:
  8 +
  9 +# Redistributions of source code must retain the above copyright notice, this list of conditions and
  10 +# the following disclaimer.
  11 +# Redistributions in binary form must reproduce the above copyright notice, this list of conditions
  12 +# and the following disclaimer in the documentation and/or other materials provided with the distribution.
  13 +
  14 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
  15 +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  16 +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  17 +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  18 +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  19 +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  20 +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  21 +# POSSIBILITY OF SUCH DAMAGE.
  22 +
  23 +from dictionary.common_func import sortArguments, sortPositions
  24 +from dictionary.models import Argument, Frame, Frame_Char_Model, \
  25 + Frame_Characteristic, Position, PositionCategory, \
  26 + sortFrameChars, sortPosCatsAsStrTab
  27 +
  28 +def jsFrameToObj(frame, lemma_entry):
  29 + # szukanie charakterystyk schematu
  30 + frame_characteristic_objs = []
  31 + frame_char_models = Frame_Char_Model.objects.order_by('priority')
  32 + for i in range(len(frame_char_models)):
  33 + frame_char_value = frame_char_models[i].frame_char_values.get(value=frame['characteristics'][i])
  34 + frame_char_type = frame_char_models[i].model_name
  35 + try:
  36 + frame_char_obj = Frame_Characteristic.objects.get(type=frame_char_type, value=frame_char_value)
  37 + except Frame_Characteristic.DoesNotExist:
  38 + frame_char_obj = Frame_Characteristic(type=frame_char_type, value=frame_char_value)
  39 + frame_char_obj.save()
  40 + frame_characteristic_objs.append(frame_char_obj)
  41 +
  42 + positions_objs = []
  43 + for position in frame['positions']:
  44 + if len(position['arguments']) > 0:
  45 + pos_obj = jsPosToObj(position)
  46 + positions_objs.append(pos_obj)
  47 +
  48 + sorted_positions = []
  49 + sorted_pos_dict = sortPositions(positions_objs)
  50 + last_pos_dict = None
  51 + for pos_dict in sorted_pos_dict:
  52 + sorted_positions.append(pos_dict['position'])
  53 +
  54 + sort_pos_str_tab = []
  55 + for sort_pos in sorted_positions:
  56 + sort_pos_str_tab.append(sort_pos.text_rep)
  57 +
  58 + text_rep = u'%s:%s' % (':'.join(frame['characteristics']),
  59 + '+'.join(sort_pos_str_tab))
  60 +
  61 + try:
  62 + frame_obj = Frame.objects.get(text_rep=text_rep)
  63 + except Frame.DoesNotExist:
  64 + frame_obj = Frame(text_rep=text_rep)
  65 + frame_obj.save()
  66 + last_pos_obj = None
  67 + pos_obj_count = 0
  68 + for pos_obj in sorted_positions:
  69 + same_pos_db = Position.objects.filter(text_rep=pos_obj.text_rep).order_by('id')
  70 + if not last_pos_obj or last_pos_obj.text_rep != pos_obj.text_rep:
  71 + pos_obj_count = 1
  72 + frame_obj.positions.add(same_pos_db[0])
  73 + else:
  74 + pos_obj_count = pos_obj_count + 1
  75 + if pos_obj_count <= len(same_pos_db):
  76 + same_pos_obj = same_pos_db[pos_obj_count-1]
  77 + frame_obj.positions.add(same_pos_obj)
  78 + else:
  79 + same_pos_obj = Position(text_rep=pos_obj.text_rep)
  80 + same_pos_obj.save()
  81 + for category in pos_obj.categories.all():
  82 + same_pos_obj.categories.add(category)
  83 + for arg in pos_obj.arguments.all():
  84 + same_pos_obj.arguments.add(arg)
  85 + frame_obj.positions.add(same_pos_obj)
  86 + last_pos_obj = pos_obj
  87 + for frame_char in frame_characteristic_objs:
  88 + frame_obj.characteristics.add(frame_char)
  89 + if frame_obj.has_phraseologic_arguments():
  90 + frame_obj.phraseologic = True
  91 + frame_obj.save()
  92 +
  93 + return frame_obj
  94 +
  95 +def jsPosToObj(position, pos_idx=0):
  96 + categories = []
  97 + for category in position['categories']:
  98 + categories.append(category)
  99 + categories = sortPosCatsAsStrTab(categories)
  100 + arguments_objs = []
  101 + for arg in position['arguments']:
  102 + arguments_objs.append(jsArgToObj(arg))
  103 + argument_objs = sortArguments(arguments_objs)
  104 + args_str_tab = []
  105 + last_arg_obj = None
  106 + for arg_obj in argument_objs:
  107 + if not last_arg_obj or last_arg_obj.text_rep != arg_obj.text_rep:
  108 + args_str_tab.append(arg_obj.text_rep)
  109 + last_arg_obj = arg_obj
  110 + pos_text_rep = '%s{%s}' % (','.join(categories),';'.join(args_str_tab))
  111 + same_positions = Position.objects.filter(text_rep=pos_text_rep)
  112 + if len(same_positions) > 0:
  113 + pos_obj = same_positions[pos_idx]
  114 + else:
  115 + pos_obj = Position(text_rep=pos_text_rep)
  116 + pos_obj.save()
  117 + for category in categories:
  118 + category_obj = PositionCategory.objects.get(category=category)
  119 + pos_obj.categories.add(category_obj)
  120 + for arg_obj in argument_objs:
  121 + pos_obj.arguments.add(arg_obj)
  122 + return pos_obj
  123 +
  124 +def jsArgToObj(argument):
  125 + arg_obj = Argument.objects.get(text_rep=argument['text_rep'])
  126 + return arg_obj
  127 +
  128 +def frameObjToSerializableDict(lemma, frame):
  129 + frame_opinion = ''
  130 + frame_opinions_tab = lemma.frame_opinions.filter(frame__text_rep=frame.text_rep)
  131 + if frame_opinions_tab:
  132 + frame_opinion = frame_opinions_tab[0].value.value
  133 +
  134 + frame_dict = { 'id' : frame.id,
  135 + 'text_rep' : frame.text_rep,
  136 + 'characteristics' : [],
  137 + 'positions' : [],
  138 + 'opinion' : frame_opinion,
  139 + 'error' : False,
  140 + 'tooltip' : '',
  141 + 'is_phraseologic' : frame.phraseologic}
  142 +
  143 + sorted_pos_dict = sortPositions(frame.positions.all())
  144 + for position in sorted_pos_dict:
  145 + categories_str_tab = []
  146 + for category in position['position'].categories.all():
  147 + categories_str_tab.append(category.category)
  148 + categories_str_tab = sortPosCatsAsStrTab(categories_str_tab)
  149 +
  150 + position_dict = {'id' : position['position'].id,
  151 + 'text_rep' : position['position'].text_rep,
  152 + 'categories': categories_str_tab,
  153 + 'arguments' : [],
  154 + 'error' : False,
  155 + 'tooltip' : ''}
  156 +
  157 + for argument in position['arguments']:
  158 + argument_dict = { 'id' : argument.id,
  159 + 'text_rep': argument.text_rep,
  160 + 'type' : argument.type,
  161 + 'error' : False,
  162 + 'tooltip' : ''}
  163 + position_dict['arguments'].append(argument_dict)
  164 +
  165 + frame_dict['positions'].append(position_dict)
  166 +
  167 + frame_char_objs = sortFrameChars(frame.characteristics.all())
  168 + for char in frame_char_objs:
  169 + frame_dict['characteristics'].append(char.value.value)
  170 +
  171 + return frame_dict
... ...
common/morfeusz.py 0 → 100644
  1 +++ a/common/morfeusz.py
  1 +# encoding=UTF-8
  2 +
  3 +# Copyright © 2007, 2008, 2010, 2011 Jakub Wilk <jwilk@jwilk.net>
  4 +#
  5 +# Permission is hereby granted, free of charge, to any person obtaining a copy
  6 +# of this software and associated documentation files (the “Software”), to deal
  7 +# in the Software without restriction, including without limitation the rights
  8 +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9 +# copies of the Software, and to permit persons to whom the Software is
  10 +# furnished to do so, subject to the following conditions:
  11 +#
  12 +# The above copyright notice and this permission notice shall be included in
  13 +# all copies or substantial portions of the Software.
  14 +#
  15 +# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18 +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20 +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21 +# SOFTWARE.
  22 +
  23 +'''
  24 +Bindings for Morfeusz_, a Polish morphological analyser.
  25 +
  26 +.. _Morfeusz:
  27 + http://sgjp.pl/morfeusz/
  28 +'''
  29 +
  30 +from __future__ import with_statement
  31 +
  32 +import collections
  33 +import ctypes
  34 +import sys
  35 +
  36 +py3k = sys.version_info >= (3, 0)
  37 +
  38 +if py3k:
  39 + import _thread as thread
  40 +else:
  41 + import thread
  42 +if not py3k:
  43 + from itertools import izip as zip
  44 +
  45 +if py3k:
  46 + unicode = str
  47 +
  48 +__author__ = 'Jakub Wilk <jwilk@jwilk.net>'
  49 +__version__ = '0.3300'
  50 +__all__ = ['analyse', 'about', 'expand_tags', 'ATTRIBUTES', 'VALUES']
  51 +
  52 +ATTRIBUTES = '''
  53 +subst=number case gender
  54 +depr=number case gender
  55 +adj=number case gender degree
  56 +adja=
  57 +adjc=
  58 +adjp=
  59 +adv=degree
  60 +num=number case gender accommodability
  61 +numcol=number case gender accommodability
  62 +ppron12=number case gender person accentability
  63 +ppron3=number case gender person accentability post_prepositionality
  64 +siebie=case
  65 +fin=number person aspect
  66 +bedzie=number person aspect
  67 +aglt=number person aspect vocalicity
  68 +praet=number gender aspect agglutination
  69 +impt=number person aspect
  70 +imps=aspect
  71 +inf=aspect
  72 +pcon=aspect
  73 +pant=aspect
  74 +ger=number case gender aspect negation
  75 +pact=number case gender aspect negation
  76 +ppas=number case gender aspect negation
  77 +winien=number gender aspect
  78 +pred=
  79 +prep=case vocalicity
  80 +conj=
  81 +comp=
  82 +brev=fullstoppedness
  83 +burk=
  84 +interj=
  85 +qub=vocalicity
  86 +xxs=number case gender
  87 +xxx=
  88 +interp=
  89 +ign=
  90 +sp=
  91 +'''
  92 +ATTRIBUTES = \
  93 +dict(
  94 + (key, tuple(values.split()))
  95 + for line in ATTRIBUTES.splitlines() if line
  96 + for (key, values) in (line.split('=', 1),)
  97 +)
  98 +
  99 +VALUES = '''
  100 +number=sg pl
  101 +case=nom gen dat acc inst loc voc
  102 +gender=m1 m2 m3 f n1 n2 p1 p2 p3
  103 +person=pri sec ter
  104 +degree=pos comp sup
  105 +aspect=imperf perf
  106 +negation=aff neg
  107 +accentability=akc nakc
  108 +post_prepositionality=npraep praep
  109 +accommodability=congr rec
  110 +agglutination=agl nagl
  111 +vocalicity=nwok wok
  112 +fullstoppedness=pun npun
  113 +'''
  114 +VALUES = \
  115 +dict(
  116 + (key, tuple(values.split()))
  117 + for line in VALUES.splitlines() if line
  118 + for (key, values) in (line.split('=', 1),)
  119 +)
  120 +
  121 +libmorfeusz = ctypes.CDLL('libmorfeusz.so.0')
  122 +
  123 +MORFOPT_ENCODING = 1
  124 +MORFEUSZ_UTF_8 = 8
  125 +
  126 +MORFOPT_WHITESPACE = 2
  127 +MORFEUSZ_SKIP_WHITESPACE = 0
  128 +MORFEUSZ_KEEP_WHITESPACE = 2
  129 +
  130 +libmorfeusz.morfeusz_set_option(MORFOPT_ENCODING, MORFEUSZ_UTF_8)
  131 +libmorfeusz_lock = thread.allocate_lock()
  132 +
  133 +class InterpEdge(ctypes.Structure):
  134 + _fields_ = \
  135 + (
  136 + ('i', ctypes.c_int),
  137 + ('j', ctypes.c_int),
  138 + ('_orth', ctypes.c_char_p),
  139 + ('_base', ctypes.c_char_p),
  140 + ('_tags', ctypes.c_char_p)
  141 + )
  142 +
  143 + if py3k:
  144 + @property
  145 + def tags(self):
  146 + if self._tags is not None:
  147 + return self._tags.decode('UTF-8')
  148 + else:
  149 + @property
  150 + def tags(self):
  151 + return self._tags
  152 +
  153 + @property
  154 + def orth(self):
  155 + if self._orth is not None:
  156 + return self._orth.decode('UTF-8')
  157 +
  158 + @property
  159 + def base(self):
  160 + if self._base is not None:
  161 + return self._base.decode('UTF-8')
  162 +
  163 +libmorfeusz_analyse = libmorfeusz.morfeusz_analyse
  164 +libmorfeusz_analyse.restype = ctypes.POINTER(InterpEdge)
  165 +libmorfeusz_about = libmorfeusz.morfeusz_about
  166 +libmorfeusz_about.restype = ctypes.c_char_p
  167 +
  168 +def expand_tags(tags, expand_dot=True, expand_underscore=True):
  169 +
  170 + if tags is None:
  171 + yield
  172 + return
  173 + tags = str(tags)
  174 + for tag in tags.split('|'):
  175 + tag = tag.split(':')
  176 + pos = tag.pop(0)
  177 + chunks = [(pos,)]
  178 + chunks += \
  179 + (
  180 + VALUES[attribute] if chunk == '_' and expand_underscore
  181 + else chunk.split('.')
  182 + for chunk, attribute in zip(tag, ATTRIBUTES[pos])
  183 + )
  184 +
  185 + if not expand_dot:
  186 + yield ':'.join('.'.join(values) for values in chunks)
  187 + continue
  188 +
  189 + def expand_chunks(i):
  190 + if i >= len(chunks):
  191 + yield ()
  192 + else:
  193 + tail = tuple(expand_chunks(i + 1))
  194 + for chunk_variant in chunks[i]:
  195 + for tail_variant in tail:
  196 + yield (chunk_variant,) + tail_variant
  197 +
  198 + for x in expand_chunks(0):
  199 + yield ':'.join(x)
  200 +
  201 +_expand_tags = expand_tags
  202 +
  203 +def _dont_expand_tags(s, **kwargs):
  204 + return [s]
  205 +
  206 +def analyse(text, expand_tags=True, expand_dot=True, expand_underscore=True, dag=False, keep_whitespace=False):
  207 + '''
  208 + Analyse the text.
  209 + '''
  210 + expand_tags = _expand_tags if expand_tags else _dont_expand_tags
  211 + text = unicode(text)
  212 + text = text.encode('UTF-8')
  213 + analyse = _analyse_as_dag if dag else _analyse_as_list
  214 + return analyse(
  215 + text=text,
  216 + expand_tags=expand_tags,
  217 + expand_dot=expand_dot,
  218 + expand_underscore=expand_underscore,
  219 + keep_whitespace=keep_whitespace
  220 + )
  221 +
  222 +def _analyse_as_dag(text, expand_tags, expand_dot, expand_underscore, keep_whitespace):
  223 + result = []
  224 + with libmorfeusz_lock:
  225 + if keep_whitespace:
  226 + if libmorfeusz.morfeusz_set_option(MORFOPT_WHITESPACE, MORFEUSZ_KEEP_WHITESPACE) != 1:
  227 + raise NotImplementedError("This version of Morfeusz doesn't support keep_whitespace")
  228 + for edge in libmorfeusz_analyse(text):
  229 + if edge.i == -1:
  230 + break
  231 + for tag in expand_tags(edge.tags, expand_dot=expand_dot, expand_underscore=expand_underscore):
  232 + result += [(edge.i, edge.j, (edge.orth, edge.base, tag))]
  233 + if keep_whitespace:
  234 + libmorfeusz.morfeusz_set_option(MORFOPT_WHITESPACE, MORFEUSZ_SKIP_WHITESPACE)
  235 + return result
  236 +
  237 +def _analyse_as_list(text, expand_tags, expand_dot, expand_underscore, keep_whitespace):
  238 + dag = collections.defaultdict(list)
  239 + with libmorfeusz_lock:
  240 + if keep_whitespace:
  241 + if libmorfeusz.morfeusz_set_option(MORFOPT_WHITESPACE, MORFEUSZ_KEEP_WHITESPACE) != 1:
  242 + raise NotImplementedError("This version of Morfeusz doesn't support keep_whitespace")
  243 + for edge in libmorfeusz_analyse(text):
  244 + if edge.i == -1:
  245 + break
  246 + for tag in expand_tags(edge.tags, expand_dot=expand_dot, expand_underscore=expand_underscore):
  247 + dag[edge.i] += [((edge.orth, edge.base, tag), edge.j)]
  248 + if keep_whitespace:
  249 + libmorfeusz.morfeusz_set_option(MORFOPT_WHITESPACE, MORFEUSZ_SKIP_WHITESPACE)
  250 + def expand_dag(i):
  251 + nexts = dag[i]
  252 + if not nexts:
  253 + yield []
  254 + else:
  255 + for head, j in nexts:
  256 + for tail in expand_dag(j):
  257 + yield [head] + tail
  258 + return list(expand_dag(0))
  259 +
  260 +def about():
  261 + '''
  262 + Return a string containing information on authors and version of the
  263 + underlying library.
  264 + '''
  265 + about = libmorfeusz_about()
  266 + try:
  267 + return about.decode('UTF-8')
  268 + except UnicodeError:
  269 + return about.decode('ISO-8859-2')
  270 +
  271 +# vim:ts=4 sw=4 et
... ...
common/templates/error.html 0 → 100644
  1 +++ a/common/templates/error.html
  1 +<p id="erroralert" style="display:{{ error|yesno:",none"}}">
  2 +{{ error }}
  3 +</p>
... ...
common/templates/message.html 0 → 100644
  1 +++ a/common/templates/message.html
  1 +<p id="messagealert" style="display:{{ alert_message|yesno:",none"}}">
  2 +{{ alert_message }}
  3 +</p>
... ...
common/templates/navigation.html 0 → 100644
  1 +++ a/common/templates/navigation.html
  1 +{% for menu_item in menu %}
  2 + <li>
  3 + <a href="{{ menu_item.url }}">
  4 + {{ menu_item.name }}
  5 + </a>
  6 + </li>
  7 +{% endfor %}
0 8 \ No newline at end of file
... ...
common/templatetags/__init__.py 0 → 100644
  1 +++ a/common/templatetags/__init__.py
... ...
common/templatetags/get.py 0 → 100644
  1 +++ a/common/templatetags/get.py
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +#Copyright (c) 2012, Bartłomiej Nitoń
  4 +#All rights reserved.
  5 +
  6 +#Redistribution and use in source and binary forms, with or without modification, are permitted provided
  7 +#that the following conditions are met:
  8 +
  9 +# Redistributions of source code must retain the above copyright notice, this list of conditions and
  10 +# the following disclaimer.
  11 +# Redistributions in binary form must reproduce the above copyright notice, this list of conditions
  12 +# and the following disclaimer in the documentation and/or other materials provided with the distribution.
  13 +
  14 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
  15 +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  16 +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  17 +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  18 +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  19 +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  20 +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  21 +# POSSIBILITY OF SUCH DAMAGE.
  22 +
  23 +from django.template import Library
  24 +
  25 +register = Library()
  26 +
  27 +@register.filter
  28 +def get(dict, arg):
  29 + return dict[arg]
0 30 \ No newline at end of file
... ...
common/templatetags/ingroup.py 0 → 100644
  1 +++ a/common/templatetags/ingroup.py
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +#Copyright (c) 2012, Bartłomiej Nitoń
  4 +#All rights reserved.
  5 +
  6 +#Redistribution and use in source and binary forms, with or without modification, are permitted provided
  7 +#that the following conditions are met:
  8 +
  9 +# Redistributions of source code must retain the above copyright notice, this list of conditions and
  10 +# the following disclaimer.
  11 +# Redistributions in binary form must reproduce the above copyright notice, this list of conditions
  12 +# and the following disclaimer in the documentation and/or other materials provided with the distribution.
  13 +
  14 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
  15 +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  16 +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  17 +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  18 +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  19 +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  20 +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  21 +# POSSIBILITY OF SUCH DAMAGE.
  22 +
  23 +from django.template import Library
  24 +
  25 +register = Library()
  26 +
  27 +@register.filter
  28 +def ingroup(user, group):
  29 + return group in user.groups.all()
... ...
common/templatetags/json.py 0 → 100644
  1 +++ a/common/templatetags/json.py
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +from django.core.serializers import serialize
  4 +from django.db.models.query import QuerySet
  5 +from django.utils import simplejson
  6 +from django.utils.safestring import mark_safe
  7 +from django.template import Library
  8 +
  9 +register = Library()
  10 +
  11 +@register.filter
  12 +def jsonify(object):
  13 + if isinstance(object, QuerySet):
  14 + return serialize('json', object)
  15 + return mark_safe(simplejson.dumps(object))
... ...
common/templatetags/script.py 0 → 100644
  1 +++ a/common/templatetags/script.py
  1 +# -*- coding: utf-8 -*-
  2 +from django import template
  3 +
  4 +register = template.Library()
  5 +
  6 +@register.simple_tag
  7 +def script():
  8 + return '<script type="text/javascript"> /* <![CDATA[ */'
  9 +
  10 +@register.simple_tag
  11 +def endscript():
  12 + return '/* ]]> */ </script>'
... ...
common/util.py 0 → 100644
  1 +++ a/common/util.py
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +import re
  4 +from htmlentitydefs import name2codepoint
  5 +from django.utils.encoding import smart_unicode, force_unicode
  6 +from django.conf.urls import defaults
  7 +from django.http import HttpResponseRedirect, Http404
  8 +
  9 +from dictionary.models import Argument, Arg_Possibility, PositionCategory
  10 +
  11 +
  12 +def error_redirect(request, error, url='/'):
  13 + request.session['error'] = error
  14 + return HttpResponseRedirect(url)
  15 +
  16 +def message_redirect(request, message, url='/'):
  17 + request.session['message'] = message
  18 + return HttpResponseRedirect(url)
  19 +
  20 +def make_form(request, form_class, *args, **kwargs):
  21 + if request.POST.get('det', '') == form_class.base_fields['det'].initial:
  22 + return form_class(*args, data=request.POST, files=request.FILES, **kwargs)
  23 + else:
  24 + return form_class(*args, **kwargs)
  25 +
  26 +def invert(l):
  27 + return dict((e,nr) for (nr,e) in enumerate(l))
  28 +
  29 +def generator_slice(generator, count):
  30 + res = []
  31 + try:
  32 + for i in range(count):
  33 + res.append(generator.next())
  34 + except StopIteration:
  35 + pass
  36 + return res
  37 +
  38 +def url(regex, view, **kwargs):
  39 + if 'name' not in kwargs:
  40 + kwargs['name'] = view
  41 + return defaults.url(regex, view, **kwargs)
  42 +
  43 +def stringify_keys(dictionary):
  44 + return dict((keyword.encode('ascii'), value)
  45 + for keyword, value in dictionary.iteritems())
  46 +
  47 +# copypasta ze standardowego modułu bisect
  48 +def bisect_left(a, x, lo=0, hi=None, cmp=None):
  49 + if cmp is None:
  50 + cmp = __builtins__.cmp
  51 + if lo < 0:
  52 + raise ValueError('lo must be non-negative')
  53 + if hi is None:
  54 + hi = len(a)
  55 + while lo < hi:
  56 + mid = (lo+hi)//2
  57 + if cmp(a[mid], x) < 0: lo = mid+1
  58 + else: hi = mid
  59 + return lo
  60 +
  61 +def triple_arg_poss(arg, positions_cats_ls):
  62 + possibilities = []
  63 + if arg:
  64 + try: # TODO czy dobrze jest pomijac takie nieistniejace, argumenty
  65 + arg_obj = Argument.objects.get(text_rep=arg)
  66 + # jesli argument nie posiada atrybutow (np. refl) i jego atrybuty nie wystepuja tylko jako realizacje to ok
  67 + if arg_obj.atributes.count() == 0 or arg_obj.has_real_only_parameter():
  68 + pass
  69 + else:
  70 + return possibilities
  71 + except Argument.DoesNotExist:
  72 + return possibilities
  73 + for poss_cat in positions_cats_ls:
  74 + if poss_cat:
  75 + try:
  76 + possibility = Arg_Possibility.objects.get(argument=arg_obj,
  77 + position_category__category=poss_cat)
  78 + except Arg_Possibility.DoesNotExist:
  79 + position_category_obj = PositionCategory.objects.get(category=poss_cat)
  80 + possibility = Arg_Possibility(argument=arg_obj,
  81 + position_category=position_category_obj)
  82 + possibility.save()
  83 + possibilities.append(possibility)
  84 + else:
  85 + try:
  86 + possibility = Arg_Possibility.objects.get(argument=arg_obj,
  87 + position_category=None)
  88 + except Arg_Possibility.DoesNotExist:
  89 + possibility = Arg_Possibility(argument=arg_obj)
  90 + possibility.save()
  91 + possibilities.append(possibility)
  92 + return possibilities
... ...