<commit_before># -*- coding: utf-8 -*-

import re
import json
import logging
import random
import time
import operator
from channels import Group
from channels import Channel
from channels.sessions import channel_session
from .models import Room
from .models import Player

log = logging.getLogger(__name__)

noEnoughPeople = '房间人数不足'
gameHasStarted = '游戏已经开始'
gameNotStarted = '游戏尚未开始'
notReady = '有人没准备好'
notRightPerson = '您本轮无法投票'
voteInfo = '您投票给 '
dayerror = '时间是白天'
nighterror = '时间是夜晚'
identification = '您的身份是 '

identificationDict = dict()
identificationDict[0] = '村民'
identificationDict[1] = '狼人'
identificationDict[2] = '预言家'
identificationDict[3] = '女巫'
identificationDict[4] = '猎人'
identificationDict[5] = '守卫'

def sendMessage(label, name, messageInfo, typo):
    message = dict()
    message['handle'] = '系统信息'
    message['typo'] = typo
    message['message'] = messageInfo
    try:
        room = Room.objects.get(label=label)
    except Room.DoesNotExist:
        log.debug('ws room does not exist label=%s', label)
        return
    m = room.messages.create(**message)
    Channel(name).send({'text': json.dumps(m.as_dict())})

def sendGroupMessage(label, messageInfo, typo):
    message = dict()
    message['handle'] = '系统信息'
    message['typo'] = typo
    message['message'] = messageInfo
    try:
        room = Room.objects.get(label=label)
    except Room.DoesNotExist:
        log.debug('ws room does not exist label=%s', label)
        return
    m = room.messages.create(**message)
    Group('chat-'+label).send({'text': json.dumps(m.as_dict())})

def judgement(label):
    try:
        room = Room.objects.get(label=label)
    except Room.DoesNotExist:
        log.debug('ws room does not exist label=%s', label)
        return -1
    roleList = room.roleList.split(",")
    cunMin = roleList[0]
    langRen = roleList[1]
    shenMin = room.playerNumber - cunMin - langRen
    for player in room.players.all():
        if player.alive == 0:
            if player.identification == 0:
                cunMin = cunMin - 1
            elif player.identification == 1:
                langRen = langRen - 1
            else:
                shenMin = shenMin - 1
    if cunMin == 0 or shenMin == 0 or langRen >= cunMin + shenMin:
        return 1
    elif langRen == 0:
        return 2
    else:
        return 0

def judgementView(label, name):
    try:
        room = Room.objects.get(label=label)
    except Room.DoesNotExist:
        log.debug('ws room does not exist label=%s', label)
        sendMessage(label, name, '房间不存在!', 'error')
        return
    cunmin = ''
    langren = ''
    yuyanjia = ''
    nvwu = ''
    shouwei = ''
    lieren = ''
    for player in room.players.all():
        if player.identification == 0:
            cunmin = cunmin + player.position + ' '
        elif player.identification == 1:
            langren = langren + player.position + ' '
        elif player.identification == 2:
            yuyanjia = yuyanjia + player.position + ' '
        elif player.identification == 3:
            lieren = lieren + player.position + ' '
        elif player.identification == 4:
            nvwu = nvwu + player.position + ' '
        elif player.identification == 5:
            shouwei = shouwei + player.position + ' '
    Info = 'Identification list \n '
    if len(cunmin) > 0:
        Info = Info + '村民: ' + cunmin + '\n '
    if len(langren) > 0:
        Info = Info + '狼人: ' + langren + '\n '
    if len(yuyanjia) > 0:
        Info = Info + '预言家: ' + yuyanjia + '\n '
    if len(lieren) > 0:
        Info = Info + '猎人: ' + lieren + '\n '
    if len(nvwu) > 0:
        Info = Info + '女巫: ' + nvwu + '\n '
    if len(shouwei) > 0:
        Info = Info + '守卫: ' + shouwei + '\n '
    sendMessage(label, name, Info, 'message')

def processVote(label):
    try:
        room = Room.objects.get(label=label)
    except Room.DoesNotExist:
        log.debug('ws room does not exist label=%s', label)
        return -1, 'ws room does not exist label=' + label
    count = dict()
    info = dict()
    vote = dict()
    voteList = room.voteList.split(',')
    for i in xrange(0,len(voteList),2):
        voter = voteList[i]
        target = voteList[i + 1]
        if int(target) < 1 or int(target) > room.playerNumber:
            continue
        elif voter in vote:
            continue
        else:
            if room.players.filter(position=voter).alive is 0:
                continue
            vote[voter] = target
            if target not in info:
                info[target] = info[target] + ',' + voter
            else:
                info[target] = '' + voter
            weight = 1
            if room.players.filter(position=voter).jingzhang is 1:
                weight = 1.5
            if target in count:
                count[target] = count[target] + weight
            else:
                count[target] = weight
    deadman = max(count.iteritems(), key=operator.itemgetter(1))[0]
    systemInfo = '本轮被投的人是： ' + deadman + '\n'
    for key, val in info.iteritems():
        systemInfo = systemInfo + '投' + key + '的人有：' + val + '\n'
    return deadman, systemInfo

def room_status(label, number, gameStatus):
    try:
        room = Room.objects.get(label=label)
    except Room.DoesNotExist:
        log.debug('ws room does not exist label=%s', label)
        return -2
    if number == 1:
        sendGroupMessage(label, '天黑请闭眼！', 'message')
        return 2
    elif number == 2:
        time.sleep(10)
        sendGroupMessage(label, '狼人请睁眼！', 'message')
        if room.jinghui == 1:
            sendGroupMessage(label, '狼人请确认同伴！', 'message')
            time.sleep(10)
        time.sleep(5)
        room.voteList = ''
        room.save()
        sendGroupMessage(label, '狼人请确认击杀目标！', 'message')
        time.sleep(30)
        deadman, systemInfo = processVote(label)
        room.deadman = deadman
        room.voteList = ''
        room.save()
        sendGroupMessage(label, '狼人请闭眼！', 'message')
        time.sleep(10)
    elif number == 3:
        time.sleep(10)
        sendGroupMessage(label, '预言家请睁眼！', 'message')
        time.sleep(5)
        room.voteList = ''
        room.save()
        sendGroupMessage(label, '预言家请验人！', 'message')
        time.sleep(30)
        if 2 in gameStatus:
            deadman, systemInfo = processVote(label)
            if room.players.filter(position=deadman).identification == 1:
                systemInfo = '您验得人是狼人！'
            else:
                systemInfo = '您验得人是好人！'
            for i in range(1, room.playerNumber + 1):
                player = room.players.filter(position=i).first()
                if player.identification == 2:
                    sendMessage(label,player.address,systemInfo,'message')
    elif number == 4:
        return -1

def startGame(label):
    try:
        room = Room.objects.get(label=label)
    except Room.DoesNotExist:
        log.debug('ws room does not exist label=%s', label)
        sendGroupMessage(label, 'room does not exist!', 'error')
        return
    room.gameStart = 1
    room.save()
    roleList = room.roleList.split(",")
    playerList = []
    gameStatus = []
    gameStatus.append(0)
    gameStatus.append(1)
    for i in range(0, int(roleList[0])):
        playerList.append(0)
    for i in range(0, int(roleList[1])):
        playerList.append(1)
    for i in range(0, int(roleList[2])):
        playerList.append(2)
    if roleList[2] is not 0:
        gameStatus.append(2)
    for i in range(0, int(roleList[3])):
        playerList.append(3)
    if roleList[3] is not 0:
        gameStatus.append(3)
    for i in range(0, int(roleList[4])):
        playerList.append(4)
    if roleList[4] is not 0:
        gameStatus.append(4)
    for i in range(0, int(roleList[5])):
        playerList.append(5)
    if roleList[5] is not 0:
        gameStatus.append(5)
    random.shuffle(playerList)
    for i in range(1, room.playerNumber + 1):
        player = room.players.filter(position=i).first()
        player.identification = playerList[i - 1]
        player.save()
    sendGroupMessage(label, '身份已经准备就绪!', 'message')
    status = 0
    while judgement(label) != 0:
        status = room_status(label, status, gameStatus)
    if judgement(label) == 1:
        sendGroupMessage(label, '狼人获胜！', 'message')
    else:
        sendGroupMessage(label, '好人获胜！', 'message')

@channel_session
def ws_connect(message):
    # Extract the room from the message. This expects message.path to be of the
    # form /chat/{label}/, and finds a Room if the message path is applicable,
    # and if the Room exists. Otherwise, bails (meaning this is a some othersort
    # of websocket). So, this is effectively a version of _get_object_or_404.
    try:
        prefix, label = message['path'].decode('ascii').strip('/').split('/')
        if prefix != 'chat':
            log.debug('invalid ws path=%s', message['path'])
            return
        room = Room.objects.get(label=label)

    except ValueError:
        log.debug('invalid ws path=%s', message['path'])
        return
    except Room.DoesNotExist:
        log.debug('ws room does not exist label=%s', label)
        return

    log.debug('chat connect room=%s client=%s:%s',
        room.label, message['client'][0], message['client'][1])

    if room.playerNumber == room.currentNumber:
        log.debug('room is full')
        return
    if room.gameStart == 1:
        log.debug('游戏开始!')
        return
    # Need to be explicit about the channel layer so that testability works
    # This may be a FIXME?
    Room.objects.filter(label=label).update(currentNumber=room.currentNumber + 1)
    Group('chat-'+label).add(message.reply_channel)
    message.channel_session['room'] = room.label

@channel_session
def ws_receive(message):
    # Look up the room from the channel session, bailing if it doesn't exist
    try:
        label = message.channel_session['room']
        room = Room.objects.get(label=label)
    except KeyError:
        log.debug('no room in channel_session')
        return
    except Room.DoesNotExist:
        log.debug('recieved message, buy room does not exist label=%s', label)
        return

    # Parse out a chat message from the content text, bailing if it doesn't
    # conform to the expected message format.
    try:
        data = json.loads(message['text'])
    except ValueError:
        log.debug("ws message isn't json text=%s", text)
        return

    if set(data.keys()) != set(('handle', 'message', 'typo')):
        log.debug("ws message unexpected format data=%s", data)
        return

    if data:
        player = None
        try:
            player = room.players.filter(position=data['handle']).first()
        except ValueError:
            log.debug("something is wrong")
        if player is not None:
            if player.address != message.reply_channel.name:
                log.debug("this room's position has been occupied by another guy")
                sendMessage(room.label, message.reply_channel.name, "this room's position has been occupied by another guy", 'error')
        else:
            room.players.create(position=data['handle'],address=message.reply_channel.name)
        log.debug('chat message room=%s handle=%s message=%s',
            room.label, data['handle'], data['message'])
        if data['typo'] == 'startGame':
            if room.currentNumber < room.playerNumber:
                sendMessage(room.label, message.reply_channel.name, noEnoughPeople, 'error')
            elif room.gameStart == 1:
                sendMessage(room.label, message.reply_channel.name, gameHasStarted, 'error')
            elif room.players.all().count() < room.playerNumber:
                sendMessage(room.label, message.reply_channel.name, notReady, 'error')
            else:
                sendGroupMessage(room.label, 'Game Starts!', 'message')
                startGame(label)
        elif data['typo'] == 'Vote':
                sendMessage(room.label, message.reply_channel.name, voteInfo + data['message'], 'message')
        elif data['typo'] == 'posion':
            if room.gameStart == 0:
                sendMessage(room.label, message.reply_channel.name, gameNotStarted, 'error')
        elif data['typo'] == 'heal':
            if room.gameStart == 0:
                sendMessage(room.label, message.reply_channel.name, gameNotStarted, 'error')
        elif data['typo'] == 'bloom':
            if room.gameStart == 0:
                sendMessage(room.label, message.reply_channel.name, gameNotStarted, 'error')
            elif room.dayStatus == 0:
                sendMessage(room.label, message.reply_channel.name, nighterror, 'error')
        elif data['typo'] == 'identification':
            if room.gameStart == 0:
                sendMessage(room.label, message.reply_channel.name, gameNotStarted, 'error')
            else:
                player = room.players.filter(position=data['handle']).first()
                sendMessage(room.label, message.reply_channel.name, identification + identificationDict[player.identification], 'message')
        elif data['typo'] == 'judgement':
            if room.gameStart == 0:
                sendMessage(room.label, message.reply_channel.name, gameNotStarted, 'error')
            else:
                player = room.players.filter(position=data['handle']).first
                if player.alive is 1:
                    sendMessage(room.label, message.reply_channel.name, '您在游戏中的角色还活着，无法成为法官', 'error')
                else:
                    judgementView(room.label, message.reply_channel.name)

        #m = room.messages.create(**data)

        # See above for the note about Group
        #Group('chat-'+label).send({'text': json.dumps(m.as_dict())})

@channel_session
def ws_disconnect(message):
    try:
        label = message.channel_session['room']
        room = Room.objects.get(label=label)
        Group('chat-'+label).discard(message.reply_channel)
        player = room.players.filter(address=message.reply_channel.name).first()
        if player is not None:
            Room.objects.filter(label=label).update(currentNumber=room.currentNumber - 1)
            room.players.filter(address=message.reply_channel.name).delete()
    except (KeyError, Room.DoesNotExist):
        pass
<commit_msg>try to test vote<commit_after># -*- coding: utf-8 -*-

import re
import json
import logging
import random
import time
import operator
from channels import Group
from channels import Channel
from channels.sessions import channel_session
from .models import Room
from .models import Player

log = logging.getLogger(__name__)

noEnoughPeople = '房间人数不足'
gameHasStarted = '游戏已经开始'
gameNotStarted = '游戏尚未开始'
notReady = '有人没准备好'
notRightPerson = '您本轮无法投票'
voteInfo = '您投票给 '
dayerror = '时间是白天'
nighterror = '时间是夜晚'
identification = 'Your Identification is '

identificationDict = dict()
identificationDict[0] = '村民'
identificationDict[1] = '狼人'
identificationDict[2] = '预言家'
identificationDict[3] = '女巫'
identificationDict[4] = '猎人'
identificationDict[5] = '守卫'

def sendMessage(label, name, messageInfo, typo):
    message = dict()
    message['handle'] = '系统信息'
    message['typo'] = typo
    message['message'] = messageInfo
    try:
        room = Room.objects.get(label=label)
    except Room.DoesNotExist:
        log.debug('ws room does not exist label=%s', label)
        return
    m = room.messages.create(**message)
    Channel(name).send({'text': json.dumps(m.as_dict())})

def sendGroupMessage(label, messageInfo, typo):
    message = dict()
    message['handle'] = '系统信息'
    message['typo'] = typo
    message['message'] = messageInfo
    try:
        room = Room.objects.get(label=label)
    except Room.DoesNotExist:
        log.debug('ws room does not exist label=%s', label)
        return
    m = room.messages.create(**message)
    Group('chat-'+label).send({'text': json.dumps(m.as_dict())})

def judgement(label):
    try:
        room = Room.objects.get(label=label)
    except Room.DoesNotExist:
        log.debug('ws room does not exist label=%s', label)
        return -1
    roleList = room.roleList.split(",")
    cunMin = roleList[0]
    langRen = roleList[1]
    shenMin = room.playerNumber - cunMin - langRen
    for player in room.players.all():
        if player.alive == 0:
            if player.identification == 0:
                cunMin = cunMin - 1
            elif player.identification == 1:
                langRen = langRen - 1
            else:
                shenMin = shenMin - 1
    if cunMin == 0 or shenMin == 0 or langRen >= cunMin + shenMin:
        return 1
    elif langRen == 0:
        return 2
    else:
        return 0

def judgementView(label, name):
    try:
        room = Room.objects.get(label=label)
    except Room.DoesNotExist:
        log.debug('ws room does not exist label=%s', label)
        sendMessage(label, name, '房间不存在!', 'error')
        return
    cunmin = ''
    langren = ''
    yuyanjia = ''
    nvwu = ''
    shouwei = ''
    lieren = ''
    for player in room.players.all():
        if player.identification == 0:
            cunmin = cunmin + player.position + ' '
        elif player.identification == 1:
            langren = langren + player.position + ' '
        elif player.identification == 2:
            yuyanjia = yuyanjia + player.position + ' '
        elif player.identification == 3:
            lieren = lieren + player.position + ' '
        elif player.identification == 4:
            nvwu = nvwu + player.position + ' '
        elif player.identification == 5:
            shouwei = shouwei + player.position + ' '
    Info = 'Identification list \n '
    if len(cunmin) > 0:
        Info = Info + '村民: ' + cunmin + '\n '
    if len(langren) > 0:
        Info = Info + '狼人: ' + langren + '\n '
    if len(yuyanjia) > 0:
        Info = Info + '预言家: ' + yuyanjia + '\n '
    if len(lieren) > 0:
        Info = Info + '猎人: ' + lieren + '\n '
    if len(nvwu) > 0:
        Info = Info + '女巫: ' + nvwu + '\n '
    if len(shouwei) > 0:
        Info = Info + '守卫: ' + shouwei + '\n '
    sendMessage(label, name, Info, 'message')

def processVote(label):
    try:
        room = Room.objects.get(label=label)
    except Room.DoesNotExist:
        log.debug('ws room does not exist label=%s', label)
        return -1, 'ws room does not exist label=' + label
    count = dict()
    info = dict()
    vote = dict()
    voteList = room.voteList.split(',')
    for i in xrange(0,len(voteList),2):
        voter = voteList[i]
        target = voteList[i + 1]
        if int(target) < 1 or int(target) > room.playerNumber:
            continue
        elif voter in vote:
            continue
        else:
            if room.players.filter(position=voter).alive is 0:
                continue
            vote[voter] = target
            if target not in info:
                info[target] = info[target] + ',' + voter
            else:
                info[target] = '' + voter
            weight = 1
            if room.players.filter(position=voter).jingzhang is 1:
                weight = 1.5
            if target in count:
                count[target] = count[target] + weight
            else:
                count[target] = weight
    deadman = max(count.iteritems(), key=operator.itemgetter(1))[0]
    systemInfo = '本轮被投的人是： ' + deadman + '\n'
    for key, val in info.iteritems():
        systemInfo = systemInfo + '投' + key + '的人有：' + val + '\n'
    return deadman, systemInfo

def room_status(label, number, gameStatus):
    try:
        room = Room.objects.get(label=label)
    except Room.DoesNotExist:
        log.debug('ws room does not exist label=%s', label)
        return -2
    if number == 1:
        sendGroupMessage(label, '天黑请闭眼！', 'message')
        return 2
    elif number == 2:
        time.sleep(10)
        sendGroupMessage(label, '狼人请睁眼！', 'message')
        if room.jinghui == 1:
            sendGroupMessage(label, '狼人请确认同伴！', 'message')
            time.sleep(10)
        time.sleep(5)
        room.voteList = ''
        room.save()
        sendGroupMessage(label, '狼人请确认击杀目标！', 'message')
        time.sleep(30)
        deadman, systemInfo = processVote(label)
        room.deadman = deadman
        room.voteList = ''
        room.save()
        sendGroupMessage(label, '狼人请闭眼！', 'message')
        time.sleep(10)
    elif number == 3:
        time.sleep(10)
        sendGroupMessage(label, '预言家请睁眼！', 'message')
        time.sleep(5)
        room.voteList = ''
        room.save()
        sendGroupMessage(label, '预言家请验人！', 'message')
        time.sleep(30)
        if 2 in gameStatus:
            deadman, systemInfo = processVote(label)
            if room.players.filter(position=deadman).identification == 1:
                systemInfo = '您验得人是狼人！'
            else:
                systemInfo = '您验得人是好人！'
            for i in range(1, room.playerNumber + 1):
                player = room.players.filter(position=i).first()
                if player.identification == 2:
                    sendMessage(label,player.address,systemInfo,'message')
    elif number == 4:
        return -1

def startGame(label):
    try:
        room = Room.objects.get(label=label)
    except Room.DoesNotExist:
        log.debug('ws room does not exist label=%s', label)
        sendGroupMessage(label, 'room does not exist!', 'error')
        return
    room.gameStart = 1
    room.save()
    roleList = room.roleList.split(",")
    playerList = []
    gameStatus = []
    gameStatus.append(0)
    gameStatus.append(1)
    for i in range(0, int(roleList[0])):
        playerList.append(0)
    for i in range(0, int(roleList[1])):
        playerList.append(1)
    for i in range(0, int(roleList[2])):
        playerList.append(2)
    if roleList[2] is not 0:
        gameStatus.append(2)
    for i in range(0, int(roleList[3])):
        playerList.append(3)
    if roleList[3] is not 0:
        gameStatus.append(3)
    for i in range(0, int(roleList[4])):
        playerList.append(4)
    if roleList[4] is not 0:
        gameStatus.append(4)
    for i in range(0, int(roleList[5])):
        playerList.append(5)
    if roleList[5] is not 0:
        gameStatus.append(5)
    random.shuffle(playerList)
    for i in range(1, room.playerNumber + 1):
        player = room.players.filter(position=i).first()
        player.identification = playerList[i - 1]
        player.save()
    sendGroupMessage(label, '身份已经准备就绪!', 'message')
    status = 0
    while judgement(label) != 0:
        status = room_status(label, status, gameStatus)
    if judgement(label) == 1:
        sendGroupMessage(label, '狼人获胜！', 'message')
    else:
        sendGroupMessage(label, '好人获胜！', 'message')

@channel_session
def ws_connect(message):
    # Extract the room from the message. This expects message.path to be of the
    # form /chat/{label}/, and finds a Room if the message path is applicable,
    # and if the Room exists. Otherwise, bails (meaning this is a some othersort
    # of websocket). So, this is effectively a version of _get_object_or_404.
    try:
        prefix, label = message['path'].decode('ascii').strip('/').split('/')
        if prefix != 'chat':
            log.debug('invalid ws path=%s', message['path'])
            return
        room = Room.objects.get(label=label)

    except ValueError:
        log.debug('invalid ws path=%s', message['path'])
        return
    except Room.DoesNotExist:
        log.debug('ws room does not exist label=%s', label)
        return

    log.debug('chat connect room=%s client=%s:%s',
        room.label, message['client'][0], message['client'][1])

    if room.playerNumber == room.currentNumber:
        log.debug('room is full')
        return
    if room.gameStart == 1:
        log.debug('游戏开始!')
        return
    # Need to be explicit about the channel layer so that testability works
    # This may be a FIXME?
    Room.objects.filter(label=label).update(currentNumber=room.currentNumber + 1)
    Group('chat-'+label).add(message.reply_channel)
    message.channel_session['room'] = room.label

@channel_session
def ws_receive(message):
    # Look up the room from the channel session, bailing if it doesn't exist
    try:
        label = message.channel_session['room']
        room = Room.objects.get(label=label)
    except KeyError:
        log.debug('no room in channel_session')
        return
    except Room.DoesNotExist:
        log.debug('recieved message, buy room does not exist label=%s', label)
        return

    # Parse out a chat message from the content text, bailing if it doesn't
    # conform to the expected message format.
    try:
        data = json.loads(message['text'])
    except ValueError:
        log.debug("ws message isn't json text=%s", text)
        return

    if set(data.keys()) != set(('handle', 'message', 'typo')):
        log.debug("ws message unexpected format data=%s", data)
        return

    if data:
        player = None
        try:
            player = room.players.filter(position=data['handle']).first()
        except ValueError:
            log.debug("something is wrong")
        if player is not None:
            if player.address != message.reply_channel.name:
                log.debug("this room's position has been occupied by another guy")
                sendMessage(room.label, message.reply_channel.name, "this room's position has been occupied by another guy", 'error')
        else:
            room.players.create(position=data['handle'],address=message.reply_channel.name)
        log.debug('chat message room=%s handle=%s message=%s',
            room.label, data['handle'], data['message'])
        if data['typo'] == 'startGame':
            if room.currentNumber < room.playerNumber:
                sendMessage(room.label, message.reply_channel.name, noEnoughPeople, 'error')
            elif room.gameStart == 1:
                sendMessage(room.label, message.reply_channel.name, gameHasStarted, 'error')
            elif room.players.all().count() < room.playerNumber:
                sendMessage(room.label, message.reply_channel.name, notReady, 'error')
            else:
                sendGroupMessage(room.label, 'Game Starts!', 'message')
                startGame(label)
        elif data['typo'] == 'Vote':
                sendMessage(room.label, message.reply_channel.name, voteInfo + data['message'], 'message')
        elif data['typo'] == 'posion':
            if room.gameStart == 0:
                sendMessage(room.label, message.reply_channel.name, gameNotStarted, 'error')
        elif data['typo'] == 'heal':
            if room.gameStart == 0:
                sendMessage(room.label, message.reply_channel.name, gameNotStarted, 'error')
        elif data['typo'] == 'bloom':
            if room.gameStart == 0:
                sendMessage(room.label, message.reply_channel.name, gameNotStarted, 'error')
            elif room.dayStatus == 0:
                sendMessage(room.label, message.reply_channel.name, nighterror, 'error')
        elif data['typo'] == 'identification':
            if room.gameStart == 0:
                sendMessage(room.label, message.reply_channel.name, gameNotStarted, 'error')
            else:
                player = room.players.filter(position=data['handle']).first()
                sendMessage(room.label, message.reply_channel.name, identification + identificationDict[player.identification], 'message')
        elif data['typo'] == 'judgement':
            if room.gameStart == 0:
                sendMessage(room.label, message.reply_channel.name, gameNotStarted, 'error')
            else:
                player = room.players.filter(position=data['handle']).first
                if player.alive is 1:
                    sendMessage(room.label, message.reply_channel.name, '您在游戏中的角色还活着，无法成为法官', 'error')
                else:
                    judgementView(room.label, message.reply_channel.name)

        #m = room.messages.create(**data)

        # See above for the note about Group
        #Group('chat-'+label).send({'text': json.dumps(m.as_dict())})

@channel_session
def ws_disconnect(message):
    try:
        label = message.channel_session['room']
        room = Room.objects.get(label=label)
        Group('chat-'+label).discard(message.reply_channel)
        player = room.players.filter(address=message.reply_channel.name).first()
        if player is not None:
            Room.objects.filter(label=label).update(currentNumber=room.currentNumber - 1)
            room.players.filter(address=message.reply_channel.name).delete()
    except (KeyError, Room.DoesNotExist):
        pass
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

# -----------------------------------------------------------------------------

__version__ = '0.3.37'

# -----------------------------------------------------------------------------

from ccxtpro.base.functions import inflate, inflate64, gunzip
from asyncio import ensure_future
from ccxtpro.base.fast_client import FastClient
from ccxt.async_support import Exchange as BaseExchange
from ccxt import NotSupported
from ccxtpro.base.order_book import OrderBook, IndexedOrderBook, CountedOrderBook
from ccxt.async_support.base.throttle import throttle

# -----------------------------------------------------------------------------

__all__ = [
    'BaseExchange',
    'Exchange',
]

# -----------------------------------------------------------------------------

class Exchange(BaseExchange):

    clients = {}

    # streaming-specific options
    streaming = {
        'keepAlive': 30000,
        'ping': None,
        'maxPingPongMisses': 2.0,
    }

    @staticmethod
    def inflate(data):
        return inflate(data)

    @staticmethod
    def inflate64(data):
        return inflate64(data)

    @staticmethod
    def gunzip(data):
        return gunzip(data)

    def order_book(self, snapshot={}, depth=float('inf')):
        return OrderBook(snapshot, depth)

    def indexed_order_book(self, snapshot={}, depth=float('inf')):
        return IndexedOrderBook(snapshot, depth)

    def counted_order_book(self, snapshot={}, depth=float('inf')):
        return CountedOrderBook(snapshot, depth)

    def client(self, url):
        self.clients = self.clients or {}
        if url not in self.clients:
            on_message = self.handle_message
            on_error = self.on_error
            on_close = self.on_close
            # decide client type here: aiohttp ws / websockets / signalr / socketio
            ws_options = self.safe_value(self.options, 'ws', {})
            options = self.extend(self.streaming, {
                'print': getattr(self, 'print'),
                'ping': getattr(self, 'ping', None),
                'verbose': self.verbose,
                'throttle': throttle(self.extend({
                    'loop': self.asyncio_loop,
                }, self.tokenBucket))
            }, ws_options)
            self.clients[url] = FastClient(url, on_message, on_error, on_close, options)
        return self.clients[url]

    async def after(self, future, method, *args):
        # method is bound to self instance
        return method(await future, *args)

    async def after_async(self, future, method, *args):
        return await method(await future, *args)

    async def after_dropped(self, future, method, *args):
        await future
        return await method(*args)

    async def spawn_async(self, method, *args):
        try:
            await method(*args)
        except Exception:
            # todo: handle spawned errors
            pass

    async def delay_async(self, timeout, method, *args):
        await self.sleep(timeout)
        try:
            await method(*args)
        except Exception:
            # todo: handle spawned errors
            pass

    def spawn(self, method, *args):
        ensure_future(self.spawn_async(method, *args))

    def delay(self, timeout, method, *args):
        ensure_future(self.delay_async(timeout, method, *args))

    def handle_message(self, client, message):
        always = True
        if always:
            raise NotSupported(self.id + '.handle_message() not implemented yet')
        return {}

    def sign_message(self, client, message_hash, message):
        always = True
        if always:
            raise NotSupported(self.id + '.sign_message() not implemented yet')
        return {}

    async def connect_client(self, client, message_hash, message=None, subscribe_hash=None, subscription=None):
        # todo: calculate the backoff using the clients cache
        backoff_delay = 0
        try:
            # base exchange self.open starts the aiohttp Session in an async context
            self.open()
            await client.connect(self.session, backoff_delay)
            if subscribe_hash not in client.subscriptions:
                client.subscriptions[subscribe_hash] = subscription or True
                if self.enableRateLimit and client.throttle:
                    options = self.safe_value(self.options, 'ws', {})
                    rateLimit = self.safe_integer(options, 'rateLimit', self.rateLimit)
                    await client.throttle(rateLimit)
                # todo: decouple signing from subscriptions
                if message:
                    message = self.sign_message(client, message_hash, message)
                    await client.send(message)
        except Exception as e:
            client.reject(e, message_hash)
            if self.verbose:
                self.print(self.iso8601(self.milliseconds()), 'connect_client', 'Exception', e)

    async def watch(self, url, message_hash, message=None, subscribe_hash=None, subscription=None):
        client = self.client(url)
        future = client.future(message_hash)
        await self.connect_client(client, message_hash, message, subscribe_hash, subscription)
        return await future

    def on_error(self, client, error):
        if client.url in self.clients and self.clients[client.url].error:
            del self.clients[client.url]

    def on_close(self, client, error):
        if client.error:
            # connection closed due to an error, do nothing
            pass
        else:
            # server disconnected a working connection
            if client.url in self.clients:
                del self.clients[client.url]

    async def close(self):
        keys = list(self.clients.keys())
        for key in keys:
            await self.clients[key].close()
            if key in self.clients:
                del self.clients[key]
        return await super(Exchange, self).close()

    def limit_order_book(self, orderbook, symbol, limit=None, params={}):
        return orderbook.limit(limit)
<commit_msg>cancelederror<commit_after># -*- coding: utf-8 -*-

# -----------------------------------------------------------------------------

__version__ = '0.3.37'

# -----------------------------------------------------------------------------

from ccxtpro.base.functions import inflate, inflate64, gunzip
from asyncio import ensure_future
from ccxtpro.base.fast_client import FastClient
from ccxt.async_support import Exchange as BaseExchange
from ccxt import NotSupported
from ccxtpro.base.order_book import OrderBook, IndexedOrderBook, CountedOrderBook
from ccxt.async_support.base.throttle import throttle
import asyncio

# -----------------------------------------------------------------------------

__all__ = [
    'BaseExchange',
    'Exchange',
]

# -----------------------------------------------------------------------------

class Exchange(BaseExchange):

    clients = {}

    # streaming-specific options
    streaming = {
        'keepAlive': 30000,
        'ping': None,
        'maxPingPongMisses': 2.0,
    }

    @staticmethod
    def inflate(data):
        return inflate(data)

    @staticmethod
    def inflate64(data):
        return inflate64(data)

    @staticmethod
    def gunzip(data):
        return gunzip(data)

    def order_book(self, snapshot={}, depth=float('inf')):
        return OrderBook(snapshot, depth)

    def indexed_order_book(self, snapshot={}, depth=float('inf')):
        return IndexedOrderBook(snapshot, depth)

    def counted_order_book(self, snapshot={}, depth=float('inf')):
        return CountedOrderBook(snapshot, depth)

    def client(self, url):
        self.clients = self.clients or {}
        if url not in self.clients:
            on_message = self.handle_message
            on_error = self.on_error
            on_close = self.on_close
            # decide client type here: aiohttp ws / websockets / signalr / socketio
            ws_options = self.safe_value(self.options, 'ws', {})
            options = self.extend(self.streaming, {
                'print': getattr(self, 'print'),
                'ping': getattr(self, 'ping', None),
                'verbose': self.verbose,
                'throttle': throttle(self.extend({
                    'loop': self.asyncio_loop,
                }, self.tokenBucket))
            }, ws_options)
            self.clients[url] = FastClient(url, on_message, on_error, on_close, options)
        return self.clients[url]

    async def after(self, future, method, *args):
        # method is bound to self instance
        return method(await future, *args)

    async def after_async(self, future, method, *args):
        return await method(await future, *args)

    async def after_dropped(self, future, method, *args):
        await future
        return await method(*args)

    async def spawn_async(self, method, *args):
        try:
            await method(*args)
        except Exception:
            # todo: handle spawned errors
            pass

    async def delay_async(self, timeout, method, *args):
        await self.sleep(timeout)
        try:
            await method(*args)
        except Exception:
            # todo: handle spawned errors
            pass

    def spawn(self, method, *args):
        ensure_future(self.spawn_async(method, *args))

    def delay(self, timeout, method, *args):
        ensure_future(self.delay_async(timeout, method, *args))

    def handle_message(self, client, message):
        always = True
        if always:
            raise NotSupported(self.id + '.handle_message() not implemented yet')
        return {}

    def sign_message(self, client, message_hash, message):
        always = True
        if always:
            raise NotSupported(self.id + '.sign_message() not implemented yet')
        return {}

    async def connect_client(self, client, message_hash, message=None, subscribe_hash=None, subscription=None):
        # todo: calculate the backoff using the clients cache
        backoff_delay = 0
        try:
            # base exchange self.open starts the aiohttp Session in an async context
            self.open()
            await client.connect(self.session, backoff_delay)
            if subscribe_hash not in client.subscriptions:
                client.subscriptions[subscribe_hash] = subscription or True
                if self.enableRateLimit and client.throttle:
                    options = self.safe_value(self.options, 'ws', {})
                    rateLimit = self.safe_integer(options, 'rateLimit', self.rateLimit)
                    await client.throttle(rateLimit)
                # todo: decouple signing from subscriptions
                if message:
                    message = self.sign_message(client, message_hash, message)
                    await client.send(message)
        except Exception as e:
            client.reject(e, message_hash)
            if self.verbose:
                self.print(self.iso8601(self.milliseconds()), 'connect_client', 'Exception', e)

    async def watch(self, url, message_hash, message=None, subscribe_hash=None, subscription=None):
        client = self.client(url)
        future = client.future(message_hash)
        await self.connect_client(client, message_hash, message, subscribe_hash, subscription)
        try:
            return await future
        except asyncio.CancelledError as e:
            await self.close()
            raise e

    def on_error(self, client, error):
        if client.url in self.clients and self.clients[client.url].error:
            del self.clients[client.url]

    def on_close(self, client, error):
        if client.error:
            # connection closed due to an error, do nothing
            pass
        else:
            # server disconnected a working connection
            if client.url in self.clients:
                del self.clients[client.url]

    async def close(self):
        keys = list(self.clients.keys())
        for key in keys:
            await self.clients[key].close()
            if key in self.clients:
                del self.clients[key]
        return await super(Exchange, self).close()

    def limit_order_book(self, orderbook, symbol, limit=None, params={}):
        return orderbook.limit(limit)
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
import argparse
import re

def parse_arguments():
    #
    parser = argparse.ArgumentParser(description='')
    #
    group_main = parser.add_argument_group('Main Parameters')
    group_main.add_argument('-i', '--input_fastx', metavar='FASTX',
                            type=argparse.FileType('r', 0), default='-',
                            help='Input reads file (fasta or fastq format)')
    group_main.add_argument('-d', '--ref_db', metavar='FASTA',
                            type=argparse.FileType('r', 0),
                            help='Reference database (fasta format, with Silva taxo headers)')
    group_main.add_argument('-o', '--output_contigs', metavar='OUTPUT',
                            type=str, default='DEFAULTNAME',
                            help='Output contigs file (fasta format)')
    group_main.add_argument('-s', '--steps', metavar='INT',
                            type=int, nargs='+', default=[1,2,3,4,5],
                            help='Steps to execute')
    #
    group_perf = parser.add_argument_group('Performance')
    group_perf.add_argument('--cpu', metavar='INT',
                            type=int, default=3,
                            help='Max number of CPU to use')
    #
    group_db = parser.add_argument_group('Ref DB pre-processing (Step 0)')
    group_db.add_argument('--clustering_id_threshold', metavar='REAL',
                          type=float, default=0.95,
                          help='Identity threshold for clustering')
    #
    group_mapping = parser.add_argument_group('Mapping (Step 1)')
    group_mapping.add_argument('--best', metavar='INT',
                               type=int, default=10,
                               help='Get up to --best good alignments per read')
    #
    group_filt = parser.add_argument_group('Alignment Filtering (Step 2)')
    group_filt.add_argument('--score_threshold', metavar='REAL',
                            type=float, default=0.9,
                            help='Score threshold (real between 0 and 1)')
    group_filt.add_argument('--geometric_mode', action='store_true',
                            help='Use geometric mode filtering')
    #
    group_ovg = parser.add_argument_group('Overlap Graph Building (Step 3)')
    group_ovg.add_argument('--min_identity', metavar='REAL',
                           type=float, default=1.0,
                           help='Minimum identity of an overlap between 2 reads')
    group_ovg.add_argument('--min_overlap_length', metavar='INT',
                           type=int, default=50,
                           help='Minimum length of an overlap')
    group_ovg.add_argument('--multi', action='store_true',
                           help='Use multi-ref mode')
    #
    group_gcomp = parser.add_argument_group('Graph Compaction & Contig Identification (Step 4)')
    group_gcomp.add_argument('--min_read_node', metavar='INT',
                             type=int, default=1,
                             help='Minimum number of read to keep a node')
    group_gcomp.add_argument('--min_overlap_edge', metavar='INT',
                             type=int, default=1,
                             help='Minimum number of overlap to keep an edge')
    #
    group_lca = parser.add_argument_group('LCA Labelling (Step 5)')
    group_lca.add_argument('--quorum', metavar='FLOAT',
                           type=float, default=0.51,
                           help='Quorum for LCA computing')
    #
    group_ass = parser.add_argument_group('Contig Assembly (Step 6)')

    args = parser.parse_args()
    #
    return args

if __name__ == '__main__':

    # Arguments parsing
    args = parse_arguments()

    steps_set = frozenset(args.steps)
    print steps_set

    # STEP 1: Mappping
    if 1 in steps_set:
        sys.stdout.write('## Mapping step (1):\n')

    exit(0)

<commit_msg>Improved parameter parsing<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
import argparse
import re

matamog_dir = os.path.realpath(sys.argv[0])[:-18]
sumaclust_bin = matamog_dir + '/bin/sumaclust'
extract_taxo_bin = matamog_dir + '/bin/extract_taxo_from_fasta.py'
clean_name_bin = matamog_dir + '/bin/fasta_clean_name.py'

class DefaultHelpParser(argparse.ArgumentParser):
    """
    This is a slightly modified argparse parser to display the full help
    on parser error instead of only usage
    """
    def error(self, message):
        sys.stderr.write('\nerror: %s\n\n' % message)
        self.print_help()
        sys.exit(2)

def parse_arguments():
    """
    Parse the command line, and check if arguments are correct
    """
    #
    parser = DefaultHelpParser(description='Matamog',
                               # to precisely format help display
                               formatter_class=lambda prog: argparse.HelpFormatter(prog, width=120, max_help_position=80))
    #
    group_main = parser.add_argument_group('Main Parameters')
    group_main.add_argument('-i', '--input_fastx', metavar='FASTX',
                            type=argparse.FileType('r', 0), default='-',
                            help='Input reads file (fasta or fastq format)')
    group_main.add_argument('-d', '--ref_db', metavar='FASTA',
                            type=argparse.FileType('r', 0), required=True,
                            help='Reference database (fasta format, with Silva taxo headers)')
    group_main.add_argument('-o', '--output_contigs', metavar='OUTPUT',
                            type=str, default='DEFAULTNAME',
                            help='Output contigs file (fasta format)')
    group_main.add_argument('-s', '--steps', metavar='INT',
                            type=int, nargs='+', default=[1,2,3,4,5,6,7],
                            help='Steps to execute')
    #
    group_perf = parser.add_argument_group('Performance')
    group_perf.add_argument('--cpu', metavar='INT',
                            type=int, default=3,
                            help='Max number of CPU to use')
    group_perf.add_argument('--max_memory', metavar='INT',
                            type=int, default=-1,
                            help='Maximum memory to use (in MBi). Default is auto')
    #
    group_db = parser.add_argument_group('Ref DB pre-processing (Step 1)')
    group_db.add_argument('--clustering_id_threshold', metavar='REAL',
                          type=float, default=0.95,
                          help='Identity threshold for clustering')
    #
    group_mapping = parser.add_argument_group('Mapping (Step 2)')
    group_mapping.add_argument('--best', metavar='INT',
                               type=int, default=10,
                               help='Get up to --best good alignments per read')
    #
    group_filt = parser.add_argument_group('Alignment Filtering (Step 3)')
    group_filt.add_argument('--score_threshold', metavar='REAL',
                            type=float, default=0.9,
                            help='Score threshold (real between 0 and 1)')
    group_filt.add_argument('--geometric_mode', action='store_true',
                            help='Use geometric mode filtering')
    #
    group_ovg = parser.add_argument_group('Overlap Graph Building (Step 4)')
    group_ovg.add_argument('--min_identity', metavar='REAL',
                           type=float, default=1.0,
                           help='Minimum identity of an overlap between 2 reads')
    group_ovg.add_argument('--min_overlap_length', metavar='INT',
                           type=int, default=50,
                           help='Minimum length of an overlap')
    group_ovg.add_argument('--multi', action='store_true',
                           help='Use multi-ref mode')
    #
    group_gcomp = parser.add_argument_group('Graph Compaction & Contig Identification (Step 5)')
    group_gcomp.add_argument('--min_read_node', metavar='INT',
                             type=int, default=1,
                             help='Minimum number of read to keep a node')
    group_gcomp.add_argument('--min_overlap_edge', metavar='INT',
                             type=int, default=1,
                             help='Minimum number of overlap to keep an edge')
    #
    group_lca = parser.add_argument_group('LCA Labelling (Step 6)')
    group_lca.add_argument('--quorum', metavar='FLOAT',
                           type=float, default=0.51,
                           help='Quorum for LCA computing')
    #
    group_ass = parser.add_argument_group('Contig Assembly (Step 7)')
    #
    args = parser.parse_args()

    # Arguments checking

    # check if steps are in proper range
    steps_set = set(args.steps)
    if len(steps_set - set(range(1, 8))) > 0:
        raise Exception("steps not in range [1,7]")

    #
    return args

def print_intro(args):
    """
    Print the introduction
    """

    sys.stdout.write("""
#################################
           MATAMOG
#################################
    \n""")

    #~ sys.stdout.write('PARAM: Executable  = {0}\n'.format(os.path.abspath(os.path.dirname(os.path.realpath(sys.argv[0])))))
    sys.stdout.write('PARAM: Matamog dir = {0}\n'.format(matamog_dir))
    sys.stdout.write('PARAM: Input Fastx = {0}\n'.format(args.input_fastx.name))
    sys.stdout.write('PARAM: Ref DB      = {0}\n'.format(args.ref_db.name))
    sys.stdout.write('PARAM: Steps       = {0}\n'.format(args.steps))
    sys.stdout.write('\n')

    return 0

if __name__ == '__main__':

    # Arguments parsing
    args = parse_arguments()

    #
    print_intro(args)

    #
    steps_set = frozenset(args.steps)

    # STEP 1: Ref DB pre-processing
    if 1 in steps_set:
        sys.stdout.write('## Ref DB pre-processing step (1):\n')

        #~ sumaclust_command_line = sumaclust_bin + ' '

    exit(0)

<|endoftext|>


<commit_before>import hashlib
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.core.mail import send_mail
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.views.decorators.cache import never_cache
from alert.donate.dwolla import process_dwolla_payment
from alert.donate.paypal import process_paypal_payment
from alert.donate.forms import DonationForm, UserForm, ProfileForm
from alert.donate.stripe_helpers import process_stripe_payment
from alert.userHandling.models import UserProfile

import logging

logger = logging.getLogger(__name__)

@login_required
@never_cache
def view_donations(request):
    return render_to_response('profile/donations.html',
                              {'private': False},
                              RequestContext(request))

def send_thank_you_email(donation):
    profile = donation.userprofile_set.all()[0]
    email_subject = 'Thanks for your donation to the Free Law Project!'
    email_body = ('Hello %s,\n\nThanks for your donation of $%0.2f to the Free '
                  'Law Project. We are currently using donations like yours '
                  'for a variety of important projects that would never exist '
                  'without your help.\n\n'

                  'We are a federally-recognized 501(c)(3) public charity '
                  'and a California non-profit public benefit corporation. '
                  'Our EIN is %s.\n\n'

                  'If you have any questions about your donation, please '
                  'don\'t hesitate to get in touch.\n\n'

                  'Thanks again,\n\n'
                  'Michael Lissner and Brian Carver\n'
                  'Founders of Free Law Project\n'
                  'http://freelawproject.org/contact/') % \
                 (profile.user.first_name, donation.amount, settings.EIN, )
    send_mail(
        email_subject,
        email_body,
        'Free Law Project <donate@freelawproject.org>',
        [profile.user.email]
    )

def route_and_process_donation(cd_donation_form, cd_profile_form,
                               cd_user_form, stripe_token):
    """Routes the donation to the correct payment provider, then normalizes
    its response.

    Returns a dict with:
     - message: Any error messages that apply
     - status: The status of the payment for the database
     - payment_id: The ID of the payment
    """
    if cd_donation_form['payment_provider'] == 'dwolla':
        # Bad response:  '{"Result":"Failure","Message":"Invalid application credentials."}'
        # Good response: '{"Result":"Success","CheckoutId":"aba88bed-b525-48a4-93fd-9f7d1ec3f57b"}'
        response = process_dwolla_payment(
            cd_donation_form,
            cd_profile_form,
            cd_user_form,
            test=settings.PAYMENT_TESTING_MODE
        )
        if response['result'] == 'Success':
            response = {
                'message': None,  # Dwolla has no messages when successful
                'status': 0,  # AWAITING_PAYMENT
                'payment_id': response['payment_id'],
                'redirect': response['redirect']
            }
        else:
            response = {
                'message': response['message'],
                'status': 1,  # ERROR
                'payment_id': None,
                'redirect': None,
            }
    elif cd_donation_form['payment_provider'] == 'paypal':
        response = process_paypal_payment(cd_donation_form)
        if response['result'] == 'created':
            response = {
                'message': None,
                'status': 0,  # AWAITING_PAYMENT
                'payment_id': response['payment_id'],
                'transaction_id': response['transaction_id'],
                'redirect': response['redirect'],
            }
        else:
            response = {
                'message': 'We had an error working with PayPal. Please try '
                           'another payment method.',
                'status': 1,  # ERROR
                'payment_id': None,
                'redirect': None,
            }
    elif cd_donation_form['payment_provider'] == 'cc':
        response = process_stripe_payment(
            cd_donation_form,
            cd_user_form,
            stripe_token
        )
    else:
        response = None
    return response

def donate(request):
    """Load the donate page or process a submitted donation.

    This page has several branches. The logic is as follows:
        if GET:
            --> Load the page
        elif POST:
            if user is anonymous:
                if email address on record as a stub account:
                    --> Use it.
                elif new email address or a non-stub account:
                    --> We cannot allow anonymous people to update real
                        accounts, or this is a new email address, so create a
                        new stub account.
            elif user is logged in:
                --> associate with account.

            We now have an account. Process the payment and associate it.
    """

    message = None
    if request.method == 'POST':
        donation_form = DonationForm(request.POST)

        if request.user.is_anonymous():
            # Either this is a new account, a stubbed one, or a user that's
            # simply not logged into their account
            try:
                stub_account = User.objects.filter(
                    profile__stub_account=True).get(
                    email__iexact=request.POST.get('email')
                )
            except User.DoesNotExist:
                stub_account = False

            if stub_account:
                # We use the stub account and anonymous users even are allowed
                # to update it. This is OK, because we don't care too much
                # about the accuracy of this data. Later if/when this becomes
                # a real account, anonymous users won't be able to update this
                # information -- that's what matters.
                user_form = UserForm(
                    request.POST,
                    instance=stub_account
                )
                profile_form = ProfileForm(
                    request.POST,
                    instance=stub_account.profile
                )
            else:
                # Either a regular account or an email address we've never
                # seen before. Create a new user from the POST data.
                user_form = UserForm(request.POST)
                profile_form = ProfileForm(request.POST)
        else:
            user_form = UserForm(
                request.POST,
                instance=request.user
            )
            profile_form = ProfileForm(
                request.POST,
                instance=request.user.profile
            )

        if all([donation_form.is_valid(),
                user_form.is_valid(),
                profile_form.is_valid()]):
            # Process the data in form.cleaned_data
            cd_donation_form = donation_form.cleaned_data
            cd_user_form = user_form.cleaned_data
            cd_profile_form = profile_form.cleaned_data
            stripe_token = request.POST.get('stripeToken')

            # Route the payment to a payment provider
            response = route_and_process_donation(
                cd_donation_form,
                cd_profile_form,
                cd_user_form,
                stripe_token
            )
            logger.info("Payment routed with response: %s" % response)

            if response['status'] == 0:
                d = donation_form.save(commit=False)
                d.status = response['status']
                d.payment_id = response['payment_id']
                d.transaction_id = response.get('transaction_id')  # Will only work for Paypal.
                d.save()

                if request.user.is_anonymous() and not stub_account:
                    # Create a stub account with an unusable password
                    new_user = User.objects.create_user(
                        # Username can only be 30 chars long. Use a hash of the
                        # email address to reduce the odds of somebody
                        # wanting to create an account that already exists.
                        # We'll change this to good values later, when the stub
                        # account is upgraded to a real account with a real
                        # username.
                        hashlib.md5(request.POST.get('email')).hexdigest()[:30],
                        cd_user_form['email'],
                    )
                    new_user.first_name = cd_user_form['first_name']
                    new_user.last_name = cd_user_form['last_name']
                    new_user.save()
                    profile = UserProfile(
                        user=new_user,
                        stub_account=True,
                        address1=cd_profile_form['address1'],
                        address2=cd_profile_form.get('address2'),
                        city=cd_profile_form['city'],
                        state=cd_profile_form['state'],
                        zip_code=cd_profile_form['zip_code'],
                        wants_newsletter=cd_profile_form['wants_newsletter']
                    )
                    profile.save()
                else:
                    # Logged in user or an existing stub account.
                    user = user_form.save()
                    profile = profile_form.save()

                # Associate the donation with the profile
                profile.donation.add(d)
                profile.save()
                return HttpResponseRedirect(response['redirect'])

            else:
                logger.critical("Got back status of %s when making initial "
                                "request of API. Message was:\n%s" %
                                (response['status'], response['message']))
                message = response['message']
    else:
        try:
            donation_form = DonationForm(
                initial={
                    'referrer': request.GET.get('referrer')
                }
            )
            user_form = UserForm(
                initial={
                    'first_name': request.user.first_name,
                    'last_name': request.user.last_name,
                    'email': request.user.email,
                }
            )
            up = request.user.profile
            profile_form = ProfileForm(
                initial={
                    'address1': up.address1,
                    'address2': up.address2,
                    'city': up.city,
                    'state': up.state,
                    'zip_code': up.zip_code,
                    'wants_newsletter': up.wants_newsletter
                }
            )
        except AttributeError:
            # for anonymous users, who lack profile info
            user_form = UserForm()
            profile_form = ProfileForm()

    return render_to_response(
        'donate/donate.html',
        {
            'donation_form': donation_form,
            'user_form': user_form,
            'profile_form': profile_form,
            'private': False,
            'message': message,
            'stripe_public_key': settings.STRIPE_PUBLIC_KEY
        },
        RequestContext(request)
    )

def donate_complete(request):
    error = None
    if len(request.GET) > 0:
        # We've gotten some information from the payment provider
        if request.GET.get('error') == 'failure':
            if request.GET.get('error_description') == 'User Cancelled':
                error = 'User Cancelled'
            elif 'insufficient funds' in request.GET.get('error_description').lower():
                error = 'Insufficient Funds'
            return render_to_response(
                'donate/donate_complete.html',
                {
                    'error': error,
                    'private': True,
                },
                RequestContext(request),
            )

    return render_to_response(
        'donate/donate_complete.html',
        {
            'error': error,
            'private': True,
        },
        RequestContext(request)
    )
<commit_msg>Tests found a bug! Fixed.<commit_after>import hashlib
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.core.mail import send_mail
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.views.decorators.cache import never_cache
from alert.donate.dwolla import process_dwolla_payment
from alert.donate.paypal import process_paypal_payment
from alert.donate.forms import DonationForm, UserForm, ProfileForm
from alert.donate.stripe_helpers import process_stripe_payment
from alert.userHandling.models import UserProfile

import logging

logger = logging.getLogger(__name__)

@login_required
@never_cache
def view_donations(request):
    return render_to_response('profile/donations.html',
                              {'private': False},
                              RequestContext(request))

def send_thank_you_email(donation):
    profile = donation.donors.all()[0]
    email_subject = 'Thanks for your donation to the Free Law Project!'
    email_body = ('Hello %s,\n\nThanks for your donation of $%0.2f to the Free '
                  'Law Project. We are currently using donations like yours '
                  'for a variety of important projects that would never exist '
                  'without your help.\n\n'

                  'We are a federally-recognized 501(c)(3) public charity '
                  'and a California non-profit public benefit corporation. '
                  'Our EIN is %s.\n\n'

                  'If you have any questions about your donation, please '
                  'don\'t hesitate to get in touch.\n\n'

                  'Thanks again,\n\n'
                  'Michael Lissner and Brian Carver\n'
                  'Founders of Free Law Project\n'
                  'http://freelawproject.org/contact/') % \
                 (profile.user.first_name, donation.amount, settings.EIN, )
    send_mail(
        email_subject,
        email_body,
        'Free Law Project <donate@freelawproject.org>',
        [profile.user.email]
    )

def route_and_process_donation(cd_donation_form, cd_profile_form,
                               cd_user_form, stripe_token):
    """Routes the donation to the correct payment provider, then normalizes
    its response.

    Returns a dict with:
     - message: Any error messages that apply
     - status: The status of the payment for the database
     - payment_id: The ID of the payment
    """
    if cd_donation_form['payment_provider'] == 'dwolla':
        # Bad response:  '{"Result":"Failure","Message":"Invalid application credentials."}'
        # Good response: '{"Result":"Success","CheckoutId":"aba88bed-b525-48a4-93fd-9f7d1ec3f57b"}'
        response = process_dwolla_payment(
            cd_donation_form,
            cd_profile_form,
            cd_user_form,
            test=settings.PAYMENT_TESTING_MODE
        )
        if response['result'] == 'Success':
            response = {
                'message': None,  # Dwolla has no messages when successful
                'status': 0,  # AWAITING_PAYMENT
                'payment_id': response['payment_id'],
                'redirect': response['redirect']
            }
        else:
            response = {
                'message': response['message'],
                'status': 1,  # ERROR
                'payment_id': None,
                'redirect': None,
            }
    elif cd_donation_form['payment_provider'] == 'paypal':
        response = process_paypal_payment(cd_donation_form)
        if response['result'] == 'created':
            response = {
                'message': None,
                'status': 0,  # AWAITING_PAYMENT
                'payment_id': response['payment_id'],
                'transaction_id': response['transaction_id'],
                'redirect': response['redirect'],
            }
        else:
            response = {
                'message': 'We had an error working with PayPal. Please try '
                           'another payment method.',
                'status': 1,  # ERROR
                'payment_id': None,
                'redirect': None,
            }
    elif cd_donation_form['payment_provider'] == 'cc':
        response = process_stripe_payment(
            cd_donation_form,
            cd_user_form,
            stripe_token
        )
    else:
        response = None
    return response

def donate(request):
    """Load the donate page or process a submitted donation.

    This page has several branches. The logic is as follows:
        if GET:
            --> Load the page
        elif POST:
            if user is anonymous:
                if email address on record as a stub account:
                    --> Use it.
                elif new email address or a non-stub account:
                    --> We cannot allow anonymous people to update real
                        accounts, or this is a new email address, so create a
                        new stub account.
            elif user is logged in:
                --> associate with account.

            We now have an account. Process the payment and associate it.
    """

    message = None
    if request.method == 'POST':
        donation_form = DonationForm(request.POST)

        if request.user.is_anonymous():
            # Either this is a new account, a stubbed one, or a user that's
            # simply not logged into their account
            try:
                stub_account = User.objects.filter(
                    profile__stub_account=True).get(
                    email__iexact=request.POST.get('email')
                )
            except User.DoesNotExist:
                stub_account = False

            if stub_account:
                # We use the stub account and anonymous users even are allowed
                # to update it. This is OK, because we don't care too much
                # about the accuracy of this data. Later if/when this becomes
                # a real account, anonymous users won't be able to update this
                # information -- that's what matters.
                user_form = UserForm(
                    request.POST,
                    instance=stub_account
                )
                profile_form = ProfileForm(
                    request.POST,
                    instance=stub_account.profile
                )
            else:
                # Either a regular account or an email address we've never
                # seen before. Create a new user from the POST data.
                user_form = UserForm(request.POST)
                profile_form = ProfileForm(request.POST)
        else:
            user_form = UserForm(
                request.POST,
                instance=request.user
            )
            profile_form = ProfileForm(
                request.POST,
                instance=request.user.profile
            )

        if all([donation_form.is_valid(),
                user_form.is_valid(),
                profile_form.is_valid()]):
            # Process the data in form.cleaned_data
            cd_donation_form = donation_form.cleaned_data
            cd_user_form = user_form.cleaned_data
            cd_profile_form = profile_form.cleaned_data
            stripe_token = request.POST.get('stripeToken')

            # Route the payment to a payment provider
            response = route_and_process_donation(
                cd_donation_form,
                cd_profile_form,
                cd_user_form,
                stripe_token
            )
            logger.info("Payment routed with response: %s" % response)

            if response['status'] == 0:
                d = donation_form.save(commit=False)
                d.status = response['status']
                d.payment_id = response['payment_id']
                d.transaction_id = response.get('transaction_id')  # Will only work for Paypal.
                d.save()

                if request.user.is_anonymous() and not stub_account:
                    # Create a stub account with an unusable password
                    new_user = User.objects.create_user(
                        # Username can only be 30 chars long. Use a hash of the
                        # email address to reduce the odds of somebody
                        # wanting to create an account that already exists.
                        # We'll change this to good values later, when the stub
                        # account is upgraded to a real account with a real
                        # username.
                        hashlib.md5(request.POST.get('email')).hexdigest()[:30],
                        cd_user_form['email'],
                    )
                    new_user.first_name = cd_user_form['first_name']
                    new_user.last_name = cd_user_form['last_name']
                    new_user.save()
                    profile = UserProfile(
                        user=new_user,
                        stub_account=True,
                        address1=cd_profile_form['address1'],
                        address2=cd_profile_form.get('address2'),
                        city=cd_profile_form['city'],
                        state=cd_profile_form['state'],
                        zip_code=cd_profile_form['zip_code'],
                        wants_newsletter=cd_profile_form['wants_newsletter']
                    )
                    profile.save()
                else:
                    # Logged in user or an existing stub account.
                    user = user_form.save()
                    profile = profile_form.save()

                # Associate the donation with the profile
                profile.donation.add(d)
                profile.save()
                return HttpResponseRedirect(response['redirect'])

            else:
                logger.critical("Got back status of %s when making initial "
                                "request of API. Message was:\n%s" %
                                (response['status'], response['message']))
                message = response['message']
    else:
        try:
            donation_form = DonationForm(
                initial={
                    'referrer': request.GET.get('referrer')
                }
            )
            user_form = UserForm(
                initial={
                    'first_name': request.user.first_name,
                    'last_name': request.user.last_name,
                    'email': request.user.email,
                }
            )
            up = request.user.profile
            profile_form = ProfileForm(
                initial={
                    'address1': up.address1,
                    'address2': up.address2,
                    'city': up.city,
                    'state': up.state,
                    'zip_code': up.zip_code,
                    'wants_newsletter': up.wants_newsletter
                }
            )
        except AttributeError:
            # for anonymous users, who lack profile info
            user_form = UserForm()
            profile_form = ProfileForm()

    return render_to_response(
        'donate/donate.html',
        {
            'donation_form': donation_form,
            'user_form': user_form,
            'profile_form': profile_form,
            'private': False,
            'message': message,
            'stripe_public_key': settings.STRIPE_PUBLIC_KEY
        },
        RequestContext(request)
    )

def donate_complete(request):
    error = None
    if len(request.GET) > 0:
        # We've gotten some information from the payment provider
        if request.GET.get('error') == 'failure':
            if request.GET.get('error_description') == 'User Cancelled':
                error = 'User Cancelled'
            elif 'insufficient funds' in request.GET.get('error_description').lower():
                error = 'Insufficient Funds'
            return render_to_response(
                'donate/donate_complete.html',
                {
                    'error': error,
                    'private': True,
                },
                RequestContext(request),
            )

    return render_to_response(
        'donate/donate_complete.html',
        {
            'error': error,
            'private': True,
        },
        RequestContext(request)
    )
<|endoftext|>