Skip to content

Instantly share code, notes, and snippets.

@shiftyp
Last active June 19, 2016 18:45
Show Gist options
  • Save shiftyp/b73a8590fb236f6f231bcb91884156a4 to your computer and use it in GitHub Desktop.
Save shiftyp/b73a8590fb236f6f231bcb91884156a4 to your computer and use it in GitHub Desktop.
FP Quiz App
<!DOCTYPE html>
<html>
<head>
<title>FP Quiz App</title>
<link rel="stylesheet" href="styles.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<script type="text/javascript" src="main.js"></script>
</head>
<body>
<h1>Object Oriented &amp; Functional Programming Quiz</h1>
<div class="content">
<div class="content-inner">
<section id="quiz-intro" class="text-center">
<h2>You down with OOP &amp; FP? Well try and see...</h2>
<button class="start-button oo" type="button">Start OOP Quiz</button>
<button class="start-button fp" type="button">Start FP Quiz</button>
</section>
<section id="quiz-question" class="hidden">
<p>
Score:
<span class="current-score"></span> /
<span class="current-index"></span>
</p>
<form id="question-form">
<div class="quiz-container">
<p class="question-container text-center"></p>
<ul class="answers-container">
</ul>
</div>
<div class="text-center">
<button class="submit-answer-button" type="submit">Submit Answer</button>
</div>
</form>
</section>
<section id="quiz-outro" class="hidden text-center">
<div class="quiz-outro-message">
You got <span class="number-correct"></span> questions right out of
<span class="total-questions"></span>. Would you like to try again?
</div>
<button class="start-button oo" type="button">Start OOP Quiz</button>
<button class="start-button fp" type="button">Start FP Quiz</button>
</section>
</div>
</div>
</body>
</html>
!function() {
// --------------------------------
// Quiz Data
// --------------------------------
var ooData = [
{
prompt: 'What is not a principle of Object Oriented Programming',
answers: [
'Abstraction',
'Encapsulation',
'Inheritence',
'Polymorphism',
'Impressionism'
],
correctAnswer: 4
},{
prompt: 'What type of inheritence pattern is utilized in JavaScript?',
answers: [
'Prototypal',
'Classical',
'Trust'
],
correctAnswer: 0
},{
prompt: 'Which is better? Functional Programming or Object Oriented Programming?',
answers: [
'Object Oriented Programming',
'Functional Programming',
'Neither, everything has its uses'
],
correctAnswer: 2
}
];
var fpData = [
{
prompt: 'What is not a part of the functional programming paradigm in JavaScript?',
answers: [
'Functors',
'Monads',
'Currying',
'Closures',
'Inheritence'
],
correctAnswer: 4
},{
prompt: 'What is a function that takes a function as an argument called?',
answers: [
'Higher Order Function',
'Super Function',
'Confusing'
],
correctAnswer: 0
},{
prompt: 'Which is better? Functional Programming or Object Oriented Programming?',
answers: [
'Object Oriented Programming',
'Functional Programming',
'Neither, everything has its uses'
],
correctAnswer: 2
}
];
// ---------------------------------------
// UTILITY FUNCTIONS
// ---------------------------------------
function curriedCompose() {
var functions = Array.prototype.slice.apply(arguments);
return function () {
var args = arguments;
return curriedCompose.apply(null, functions.map(function(fn) {
if (typeof fn === 'function') {
return fn.apply(null, args);
}
}));
}
}
// ---------------------------------------
// RENDERING FUNCTIONS
// ---------------------------------------
function createShowSection(id, callback) {
return function() {
$('section').hide().filter('#quiz-' + id).show();
callback.apply(null, arguments);
};
}
function renderQuestion(question) {
$('.question-container, .answers-container').empty();
$('.question-container').text(question.prompt);
$('.answers-container').html(
question.answers.map(createAnswerHTML).join('')
);
}
function createAnswerHTML(answer, index) {
return (
'<li>' +
'<input type="radio" name="answer" value="' + index + '" id="answer' + index + '" />' +
'<label for="answer' + index + '">' + answer + '</label>' +
'</li>'
);
}
function renderScoreAndTotal(score, total) {
$('.number-correct').text(score);
$('.total-questions').text(total);
}
var showQuestion = createShowSection('question', renderQuestion);
var showOutro = createShowSection('outro', renderScoreAndTotal);
function createAlert(message) {
return function() {
alert(message);
};
}
function renderCurrentIndexAndScore(index, score) {
$('.current-index').text(index);
$('.current-score').text(score);
}
// --------------------------------
// Event Handler Functions
// --------------------------------
function attachSubmitHandler(check) {
$('#question-form').one('submit', function(event) {
event.preventDefault();
check(getAnswerFromForm(event.target));
});
}
function getAnswerFromForm(form) {
var val = $(form).find('input:checked').val();
if (val === undefined) {
return null;
} else {
return +val;
}
}
function attachQuizButtonHandler(selector, data) {
$(selector).click(createQuizHandler(data))
}
// ------------------------------------
// Quiz Logic Functions
// ------------------------------------
function createCheckAnswer(right, wrong, error) {
return function(question) {
return function(answer) {
if (answer === null) {
error();
} else if (answer === question.correctAnswer) {
right();
} else {
wrong();
}
};
}
};
function createQuestionCallback(callback) {
return function(index) {
return function(score) {
return function() {
callback(index, score);
}
};
};
};
function createQuizHandler(data) {
return function() {
var goToQuestion = curriedCompose(
createQuestionCallback(runQuiz),
createQuestionCallback(renderCurrentIndexAndScore)
);
function runQuiz(index, score) {
var advance = goToQuestion(index + 1);
var remain = goToQuestion(index);
var check = createCheckAnswer(
advance(score + 1),
advance(score),
curriedCompose(
remain(score),
createAlert('Please Select an Answer')
)
);
var question = data[index];
if (question) {
showQuestion(question);
attachSubmitHandler(check(question));
} else {
showOutro(score, index);
}
}
goToQuestion(0)(0)();
};
}
// ---------------------------------------
// DO STUFF
// ---------------------------------------
$(function() {
attachQuizButtonHandler('.start-button.oo', ooData);
attachQuizButtonHandler('.start-button.fp', fpData);
});
}();
body {
margin: 0;
background-image: url('./congruent_pentagon.png');
font-family: sans-serif;
font-size: 20px;
color: rgb(121, 127, 124);
}
h1 {
text-align: center;
}
h2 {
margin-top: 0;
}
div, form {
box-sizing: border-box;
}
button {
background-color: rgb(0, 81, 115);
color: #fff;
padding: 0.5em;
border: none;
border-radius: 5px;
font-size: 15px;
line-height: 1.5em;
margin-top: 20px;
}
.hidden {
display: none;
}
.text-center {
text-align: center;
}
.content {
position: relative;
width: 800px;
padding: 20px;
margin: 50px auto;
background-color: rgba(255, 255, 255, 0.3);
border: 1px solid rgba(255, 255, 255, 0.4);
border-bottom-width: 10px;
border-radius: 5px;
border-bottom-radius: 10px;
overflow: hidden;
}
/*
* In case you're wondering how the content seems
* to blur the background behind it this is the trick
*/
.content::before {
position: absolute;
top: -20px;
left: -20px;
content: ' ';
width: 100%;
height: 100%;
padding: 20px;
background-image: url('https://gist.githubusercontent.com/shiftyp/0e2516f91a044acfb396/raw/463fa6cddc8ff9fedddfe41b34c21ee4348e453a/congruent_pentagon.png');
background-position: center 100px;
-webkit-filter: blur(10px);
z-index: -1;
}
@media (max-width: 800px) {
.content {
width: 100%;
}
}
.answers-container li {
list-style: none;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment