~speakman/ppvalbok/trunk

« back to all changes in this revision

Viewing changes to votesys/management.py

  • Committer: Lars Luthman
  • Date: 2009-04-22 17:00:57 UTC
  • Revision ID: lars.luthman@gmail.com-20090422170057-jyl8006nmci7epli
Moved votesys to swevote, moved all non-static data to the new app ballot_system.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*-
2
 
 
3
 
import os
4
 
import codecs
5
 
import xml.dom.minidom
6
 
import math
7
 
from urllib import urlopen
8
 
from django.core import management
9
 
from django.db.models.signals import post_syncdb
10
 
from models import EarlyVotingStation, VotingStation, ZipCode, County, Municipality, Region
11
 
from regions import update_regions
12
 
import models as site_app
13
 
from transversemercator import RT90
14
 
import testdata
15
 
 
16
 
EARLY_VOTING_STATIONS_URL = \
17
 
    "http://www.val.se/val/ep2009/rostmottagning/fortidsrostning/rostlokal.xml"
18
 
 
19
 
VOTING_STATIONS_URL = \
20
 
    "http://www.val.se/val/ep2009/rostmottagning/vallokal/vallokal.xml"
21
 
 
22
 
def load_zipcodes(sender, created_models, verbosity, **kwargs):
23
 
    """
24
 
    Load zip codes into database
25
 
    """
26
 
    if not ZipCode in created_models:
27
 
        return
28
 
    ZipCode.objects.all().delete()
29
 
    management.call_command('loaddata', 'zipcodes_fixture.json')
30
 
 
31
 
def municipality_name_to_region(mname):
32
 
    """
33
 
    Return the Region object that matches the given municipality name.
34
 
    """
35
 
 
36
 
    # Sometimes mname is a tuple instead of a string. Why?
37
 
    new_name = '%s' % mname
38
 
    
39
 
    # Special cases
40
 
    if new_name == u'Gotland':
41
 
        return Region.objects.get(name=u'Gotlands valkrets')
42
 
    if new_name == u'Malm\xf6':
43
 
        return Region.objects.get(name=u'Malm\xf6 valkrets')
44
 
    if new_name == u'G\xf6teborg':
45
 
        return Region.objects.get(name=u'G\xf6teborgs valkrets')
46
 
 
47
 
    # Generic case
48
 
    consonant_list = ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm',
49
 
                      'n', 'p', 'q', 'r', 't', 'v', 'w'] # except s and x
50
 
    if new_name[-1] in consonant_list:
51
 
        new_name += 's kommun'
52
 
    else:
53
 
        new_name += ' kommun'
54
 
    return Region.objects.get(name=new_name)
55
 
 
56
 
 
57
 
def fetch_earlyvotingstations(sender, created_models, verbosity, **kwargs):
58
 
    """
59
 
    Fetch current early voting stations from Swedish Election Authority
60
 
    """
61
 
    if not EarlyVotingStation in created_models:
62
 
        return
63
 
    if verbosity >= 1:
64
 
        print "Fetching " + EARLY_VOTING_STATIONS_URL
65
 
 
66
 
    # TransverseMercator object for converting RT90 coordinates to WGS84
67
 
    tmerc = RT90()
68
 
    
69
 
    doc = xml.dom.minidom.parse(urlopen(EARLY_VOTING_STATIONS_URL))
70
 
    counties = []
71
 
    municipalities = []
72
 
    earlystations = []
73
 
    if verbosity >= 2:
74
 
        print "Parsing data..."
75
 
    for county in doc.getElementsByTagName(u'LÄN'):
76
 
        current_county = County(id=int(county.getAttribute(u'KOD')),
77
 
                                name=county.getAttribute(u'NAMN'))
78
 
        counties.append(current_county)
79
 
        for municipality in county.getElementsByTagName(u'KOMMUN'):
80
 
            m_name = municipality.getAttribute(u'NAMN')
81
 
            current_municipality = Municipality(
82
 
                id=(current_county.id*100) + int(municipality.getAttribute(u'KOD')),
83
 
                name=m_name,
84
 
                county=current_county,
85
 
                region=municipality_name_to_region(m_name))
86
 
            municipalities.append(current_municipality)
87
 
            for station in municipality.getElementsByTagName(u'RÖSTNINGSLOKAL'):
88
 
                rt90x = float(station.getAttribute(u'X') or '0')
89
 
                rt90y = float(station.getAttribute(u'Y') or '0')
90
 
                if rt90x != 0 and rt90y != 0:
91
 
                    # Yes, it's Y, X instead of X, Y. RT90 is backwards.
92
 
                    (wgs84n, wgs84e) = tmerc.inverse_project_d(rt90y, rt90x)
93
 
                else:
94
 
                    (wgs84n, wgs84e) = (0, 0)
95
 
                newstation = EarlyVotingStation(
96
 
                    county = current_county,
97
 
                    municipality = current_municipality,
98
 
                    region = current_municipality.region,
99
 
                    code = int(station.getAttribute(u'KOD') or '0'),
100
 
                    name = station.getAttribute(u'NAMN'),
101
 
                    address1 = station.getAttribute(u'ADRESS1'),
102
 
                    address2 = station.getAttribute(u'ADRESS2'),
103
 
                    address3 = station.getAttribute(u'ADRESS3'),
104
 
                    city = station.getAttribute(u'POSTORT'),
105
 
                    opening_hours = station.getAttribute(u'ÖPPETTIDER'),
106
 
                    available = station.getAttribute(u'TILLGÄNGL'),
107
 
                    status = station.getAttribute(u'STATUS'),
108
 
                    lat = str(wgs84n),
109
 
                    lon = str(wgs84e))
110
 
                earlystations.append(newstation)
111
 
    if verbosity >= 2:
112
 
        print "Counties: " + str(len(counties))
113
 
        print "Municipalities: " + str(len(municipalities))
114
 
        print "Early voting stations: " + str(len(earlystations))
115
 
    if verbosity >= 2:
116
 
        print "Storing in models..."
117
 
    County.objects.all().delete()
118
 
    for county in counties:
119
 
        county.save()
120
 
    Municipality.objects.all().delete()
121
 
    for municipality in municipalities:
122
 
        municipality.save()
123
 
    EarlyVotingStation.objects.all().delete()
124
 
    for station in earlystations:
125
 
        station.save()
126
 
    if verbosity >= 2:
127
 
        print "Early voting stations update done!"
128
 
 
129
 
def fetch_votingstations(sender, created_models, verbosity, **kwargs):
130
 
    """
131
 
    Fetch current voting stations from Swedish Election Authority
132
 
    """
133
 
    if len(VotingStation.objects.all()) > 0:
134
 
        return
135
 
    if verbosity >= 1:
136
 
        print "Fetching " + VOTING_STATIONS_URL
137
 
    doc = xml.dom.minidom.parse(urlopen(VOTING_STATIONS_URL))
138
 
 
139
 
    # TransverseMercator object for converting RT90 coordinates to WGS84
140
 
    tmerc = RT90()
141
 
 
142
 
    stations = []
143
 
    if verbosity >= 2:
144
 
        print "Parsing data..."
145
 
    for county in doc.getElementsByTagName(u'LÄN'):
146
 
        current_county = County(id=int(county.getAttribute(u'KOD')),
147
 
                                name=county.getAttribute(u'NAMN'))
148
 
        for municipality in county.getElementsByTagName(u'KOMMUN'):
149
 
            m_name = municipality.getAttribute(u'NAMN'),
150
 
            current_municipality = Municipality(
151
 
                id=(current_county.id*100) + int(municipality.getAttribute(u'KOD')),
152
 
                name=m_name,
153
 
                county=current_county,
154
 
                region=municipality_name_to_region(m_name))
155
 
            for constituency in municipality.getElementsByTagName(u'VALKRETS'):
156
 
                for station in constituency.getElementsByTagName(u'VALDISTRIKT'):
157
 
                    rt90x = float(station.getAttribute(u'X') or '0')
158
 
                    rt90y = float(station.getAttribute(u'Y') or '0')
159
 
                    if rt90x != 0 and rt90y != 0:
160
 
                        # Yes, it's Y, X instead of X, Y. RT90 is backwards.
161
 
                        (wgs84n, wgs84e) = tmerc.inverse_project_d(rt90y, rt90x)
162
 
                    else:
163
 
                        (wgs84n, wgs84e) = (0, 0)
164
 
                    vs = VotingStation(
165
 
                        county = current_county,
166
 
                        municipality = current_municipality,
167
 
                        region = current_municipality.region,
168
 
                        code = int(station.getAttribute(u'KOD') or '0'),
169
 
                        name = station.getAttribute(u'NAMN'),
170
 
                        local = station.getAttribute(u'LOKAL'),
171
 
                        address1 = station.getAttribute(u'ADRESS1'),
172
 
                        address2 = station.getAttribute(u'ADRESS2'),
173
 
                        address3 = station.getAttribute(u'ADRESS3'),
174
 
                        city = station.getAttribute(u'POSTORT'),
175
 
                        available = station.getAttribute(u'TILLGÄNGL'),
176
 
                        status = station.getAttribute(u'STATUS'),
177
 
                        done = station.getAttribute(u'KLAR'),
178
 
                        lat = str(wgs84n),
179
 
                        lon = str(wgs84e))
180
 
                    stations.append(vs)
181
 
    if verbosity >= 2:
182
 
        print "Voting stations: " + str(len(stations))
183
 
    if verbosity >= 2:
184
 
        print "Storing in models..."
185
 
    VotingStation.objects.all().delete()
186
 
    for station in stations:
187
 
        station.save()
188
 
    if verbosity >= 2:
189
 
        print "Voting stations update done!"
190
 
 
191
 
 
192
 
def load_voter_count(**kwargs):
193
 
    
194
 
    if len(VotingStation.objects.filter(voters=0)) == 0:
195
 
        return
196
 
    
197
 
    print "Loading number of voters per station..."
198
 
    sourcefile = os.path.join(os.path.dirname(__file__), "rostberattigade.skv")
199
 
    fd = open(sourcefile)
200
 
    # Skip the header line.
201
 
    line = fd.readline()
202
 
    while True:
203
 
        line = fd.readline()
204
 
        fields = line.split(';')
205
 
        if len(fields) < 45:
206
 
            break
207
 
        county_id = int(fields[11])
208
 
        municipality_id = county_id * 100 + int(fields[23])
209
 
        station_id = int(fields[35])
210
 
        voters = int(fields[37])
211
 
        station = VotingStation.objects.get(municipality__id=municipality_id,
212
 
                                            code=station_id)
213
 
        station.voters = voters
214
 
        station.save()
215
 
 
216
 
 
217
 
def update_region_statistics(**kwargs):
218
 
    print "Updating region statistics..."
219
 
    root = Region.objects.get(shortname='root')
220
 
    root.update_statistics()
221
 
 
222
 
 
223
 
post_syncdb.connect(load_zipcodes, sender=site_app)
224
 
post_syncdb.connect(update_regions, sender=site_app)
225
 
post_syncdb.connect(fetch_earlyvotingstations, sender=site_app)
226
 
post_syncdb.connect(fetch_votingstations, sender=site_app)
227
 
post_syncdb.connect(load_voter_count, sender=site_app)
228
 
post_syncdb.connect(testdata.generate_testdata, sender=site_app)
229
 
post_syncdb.connect(update_region_statistics, sender=site_app)