Skip to content

Instantly share code, notes, and snippets.

@gzoritchak
Created October 19, 2016 07:39
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gzoritchak/facabe61903545a578208b486f069c6b to your computer and use it in GitHub Desktop.
Save gzoritchak/facabe61903545a578208b486f069c6b to your computer and use it in GitHub Desktop.
package jug.dsl
val kotlinSurveyDef = createNewSurveyDef("Évaluation du kotlin user group") {
introduction = "Merci de prendre 20 secondes pour répondre à quelques questions."
val appreciation = intQuestion("Quelle est votre appréciation de la dernière session ?"){
min = 1
max = 5
}
booleanQuestion("Seriez vous prêt à recommander ce meetup à vos connaissances ?"){
showIf = { (valueOf(appreciation))> 3}
}
}
fun createNewSurveyDef(title: String, init:SurveyDef.() -> Unit) = SurveyDef(title).apply {
init()
}
fun main(args: Array<String>) {
val survey = kotlinSurveyDef.newSurvey()
survey.start()
}
class SurveyDef(val title: String){
var introduction = ""
val questionDefs = mutableListOf<QuestionDef<*>>()
fun newSurvey() = Survey(this)
fun intQuestion(title: String, init: IntQuestionDef.() -> Unit) = IntQuestionDef(title).apply {
init()
questionDefs += this
}
fun booleanQuestion(title: String, init: BooleanQuestionDef.() -> Unit) = BooleanQuestionDef(title).apply {
init()
questionDefs += this
}
}
abstract class QuestionDef<T>(val title: String){
abstract fun consignes(): String
abstract fun toValue(userInput: String):T
var showIf: Survey.()->Boolean = {true}
}
class BooleanQuestionDef(title: String):QuestionDef<Boolean>(title){
override fun consignes() = "Saisir O ou N"
override fun toValue(userInput: String) = when(userInput){
"N", "n" -> false
"O", "o" -> true
else -> error("SAISIR O ou N !!!")
}
}
class IntQuestionDef(title: String):QuestionDef<Int>(title){
override fun toValue(userInput: String): Int {
try {
val value = userInput.toInt()
if(value>max) error("Saisir un entien inférieur à $max")
if(value<min) error("Saisir un entien supérieur à $min")
return value
} catch(e: NumberFormatException) {
error("Saisir un entien")
}
}
override fun consignes() = "Saisir un entier entre $min et $max"
var min = Int.MIN_VALUE
var max = Int.MAX_VALUE
}
class Survey(val surveyDef: SurveyDef){
var status = SurveyStatus.ONGOING
val answers = mutableListOf<Answer>()
var questionIdx = 0
val currentQuestionDef : QuestionDef<*>
get() = surveyDef.questionDefs[questionIdx]
inline fun <reified T> valueOf(questionDef: QuestionDef<T>) =
answers.filterIsInstance(Answer.AnswerWithValue::class.java)
.first{it.questionDef == questionDef}.value as T
fun start(){
println(surveyDef.title)
println(surveyDef.introduction)
while (status == SurveyStatus.ONGOING){
if(currentQuestionDef.showIf(this) == false){
nextQuestion()
continue
}
println(currentQuestionDef.title)
println(currentQuestionDef.consignes())
val userInput = readLine()!!
try {
val value = currentQuestionDef.toValue(userInput)
answers +=
if(value == null) Answer.AnswerWithoutValue(currentQuestionDef)
else Answer.AnswerWithValue(currentQuestionDef, value)
nextQuestion()
} catch(e: Exception) {
System.err.println(e.message)
}
}
}
private fun nextQuestion() {
questionIdx++
if (questionIdx == surveyDef.questionDefs.size) {
status = SurveyStatus.COMPLETED
}
}
}
sealed class Answer(val questionDef: QuestionDef<*>){
class AnswerWithValue(questionDef: QuestionDef<*>, val value: Any):Answer(questionDef)
class AnswerWithoutValue(questionDef: QuestionDef<*>):Answer(questionDef)
}
enum class SurveyStatus {ONGOING, COMPLETED}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment