<repo_name>dillon2013/realtime-polls<file_sep>/app/main.py
import tornado.ioloop
import tornado.web
import os
import routes
import tornado.log
import sockjs.tornado
import pprint

tornado.log.enable_pretty_logging()

port = 8888
settings = {
    "autoreload" : True,
    "static_path": os.path.join(os.path.dirname(__file__), "static"),
    "static_hash_cache" : False,
    "compiled_template_cache" : False,
}
ChatRouter = sockjs.tornado.SockJSRouter(routes.ChatConnection, '/ws')

def make_app():
    return tornado.web.Application([
        (r"/api/users", routes.Users),
        (r"/?\w*", routes.Home)
    ] + ChatRouter.urls, **settings)

if __name__ == "__main__":
    print('server listening on port ' + str(port))
    app = make_app()
    app.listen(port)
    tornado.ioloop.IOLoop.instance().start()<file_sep>/app/routes.py
import tornado.web
import tornado.websocket
import pprint
import sockjs.tornado
import json

global questionIndex


class Home(tornado.web.RequestHandler):

    def get(self):
        # pprint.pprint(self.__dict__)
        # pprint.pprint(dir(self))
        # self.set_header('firstname', 'dillons')
        self.render('index.html')

class Users(tornado.web.RequestHandler):
    def get(self):

        users = {'users' : [{
            'name' : 'dillon',
            'age' : 29
        },{
            'name' : 'domonique',
            'age' : 29
        }]}

        self.write(users)

class ChatConnection(sockjs.tornado.SockJSConnection):
    """Chat connection implementation"""
    # Class level variable
    participants = set()
    questionIndex = 0
    numOfQuestions = 2
    state = 'index'

    def on_open(self, info):
        # Send existing clients message that someone joined
        clientJoinedData = {
            'event' : 'serverMessage',
            'message' : '{} has joined'.format(self.session.session_id),
        }
        self.broadcast(self.participants, clientJoinedData)

        # Send new client the state of application
        msg = {
            'event' : 'clientInit',
            'questionIndex' : ChatConnection.questionIndex,
            'numOfQuestions' : ChatConnection.numOfQuestions,
            'state' : ChatConnection.state
        }
        self.broadcast([self], msg)

        #add client to participants
        self.participants.add(self)

    def on_message(self, message):
        msg = json.loads(message)

        if msg['event'] == 'nextQuestion':
            if msg['questionIndex'] + 1 < ChatConnection.numOfQuestions:
                msg['previousQuestion'] = ChatConnection.questionIndex
                ChatConnection.questionIndex += 1
                msg['questionIndex'] = ChatConnection.questionIndex
                self.broadcast(self.participants, msg)

        elif msg['event'] == 'previousQuestion':
            if msg['questionIndex']  > 0:
                msg['previousQuestion'] = ChatConnection.questionIndex
                ChatConnection.questionIndex -= 1
                msg['questionIndex'] = ChatConnection.questionIndex
                self.broadcast(self.participants, msg)

        elif msg['event'] == 'stateChange':
            ChatConnection.state = msg['newState']
            self.broadcast(self.participants, msg)

        else:
            self.broadcast(self.participants, msg)


    def on_close(self):
        # Remove client from the clients list and broadcast leave message
        self.participants.remove(self)
        data = {'event' : 'serverMessage', 'data' : '{} has left'.format(self.session.session_id)}
        self.broadcast(self.participants, data)
<file_sep>/app/static/js/users/controller/usersController.js
angular.module('MainApp').controller('usersCtrl', function ($scope, $http) {
    $scope.test = 'Dillon';

    var ws = new WebSocket("ws://localhost:8888/ws");
    ws.onopen = function() {
        ws.send("Hello, world");
    };
    ws.onmessage = function (evt) {
        alert(evt.data);
    };

    $http({
        method : "GET",
        url : "/api/users"
    }).then(function mySucces(response) {
        $scope.users = response.data.users;
        console.log(response.data);
    }, function myError(response) {
        console.log(response)
    });
});<file_sep>/app/static/js/polls/model/pollsModel.js
angular.module('MainApp').factory('pollsModel', function () {
    return [
        {
            question : 'What is the Arsenal football stadium capacity?',
            answers : [
                {answer : '20,000', value : 0, selected : false},
                {answer : '55,000', value : 0, selected : false},
                {answer : '60,000', value : 0, selected : false},
                {answer : '40,000', value : 0, selected : false}
            ]
        },
        {
            question : 'What is the Tottenham football stadium capacity?',
            answers : [
                {answer : '20,000', value : 0, selected : false},
                {answer : '55,000', value : 0, selected : false},
                {answer : '10,000', value : 0, selected : false},
                {answer : '30,000', value : 0, selected : false}
            ]
        }
    ]
});<file_sep>/app/static/js/polls/controller/pollsController.js
angular.module('MainApp').controller('pollsController',
    function ($scope, pollsModel, $timeout, SocketService, $rootScope, $state) {

        $scope.questions = pollsModel;


        $scope.clickNext = function () {
            var message = {event: 'nextQuestion', questionIndex : $scope.questionIndex};
            SocketService.sock.sendMessage(message);
        };

        $scope.clickPrevious = function () {
            var message = {event: 'previousQuestion', questionIndex : $scope.questionIndex};
            SocketService.sock.sendMessage(message);
        };


        $rootScope.$on('nextQuestion', assignIndex);
        $rootScope.$on('previousQuestion', assignIndex);


        function assignIndex(event, data) {
            $timeout(function (){
                $scope.questionIndex = data.questionIndex;
            });
        }

        $scope.submitAnswer = function (questionIndex, answerIndex) {
            console.log(questionIndex, answerIndex);
        };

        $scope.selectAnswer= function (index) {
            console.log('selected answer is: ', index);
            $scope.answerIndex = index;
        };


        $rootScope.$on('chatting', function (event, data) {

        });

        $rootScope.$on('serverMessage', function (event, data) {

        });

    });<file_sep>/requirements.txt
sockjs-tornado==1.0.3
tornado==4.4.1
<file_sep>/app/static/js/login/controller/loginController.js
angular.module('MainApp').controller('loginCtrl', function ($scope) {
    $scope.test = 'Dillon'
});<file_sep>/app/static/js/app.js
angular.module('MainApp', ['ui.router']);

angular.module('MainApp').config(function($interpolateProvider, $stateProvider, $urlRouterProvider, $locationProvider) {

    $interpolateProvider.startSymbol('{$');
    $interpolateProvider.endSymbol('$}');

    $urlRouterProvider.otherwise('/');

    $stateProvider


    // ABOUT PAGE AND MULTIPLE NAMED VIEWS =================================
    .state('login', {
        url: '/login',
        templateUrl : 'static/js/login/template/loginTemplate.html'
    })

    // HOME STATES AND NESTED VIEWS ========================================
    .state('index', {
        url: '/',
        //controller: 'indexCtrl',
        templateUrl : 'static/js/index/template/indexTemplate.html'
    })

    // ABOUT PAGE AND MULTIPLE NAMED VIEWS =================================
    .state('index.polls', {
        url: 'polls',
        controller: 'pollsController',
        templateUrl : 'static/js/polls/template/pollsTemplate.html'
    });

    $locationProvider.html5Mode(true);

})

.run(function ($state,$rootScope, $timeout,SocketService) {

    $rootScope.$state = $state;
    $rootScope.questionIndex = 0;

    $rootScope.emitState = function (state) {
        SocketService.sock.sendMessage({
            event : 'stateChange',
            previousState : $state.current.name,
            newState : state
        })
    };

    $rootScope.$on('clientInit', function (event, data) {
        $timeout(function (){
            $rootScope.questionIndex = data.questionIndex;
        });

        if(data.state !== $state.current.name){
            $state.go(data.state)
        }
    });

    $rootScope.$on('stateChange', function (event, data) {
        $state.go(data.newState);
    });
});