|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include "expression.h"
|
|
|
|
|
|
|
|
union expression* webdice_const(int64_t value){
|
|
|
|
union expression* aux = (union expression*) malloc(sizeof(union expression));
|
|
|
|
|
|
|
|
(*aux).constant.id = WEBDICE_CONST;
|
|
|
|
(*aux).constant.value = value;
|
|
|
|
|
|
|
|
return aux;
|
|
|
|
}
|
|
|
|
|
|
|
|
union expression* webdice_roll(int64_t count, int64_t roll){
|
|
|
|
union expression* aux = (union expression*) malloc(sizeof(union expression));
|
|
|
|
|
|
|
|
(*aux).roll.id = WEBDICE_ROLL;
|
|
|
|
(*aux).roll.count = count;
|
|
|
|
(*aux).roll.type = roll;
|
|
|
|
|
|
|
|
return aux;
|
|
|
|
}
|
|
|
|
|
|
|
|
union expression* webdice_binary(enum binary_type type, union expression* left, union expression* right){
|
|
|
|
union expression* aux = (union expression*) malloc(sizeof(union expression));
|
|
|
|
|
|
|
|
(*aux).binary.id = WEBDICE_BINARY;
|
|
|
|
(*aux).binary.operation = type;
|
|
|
|
(*aux).binary.left = left;
|
|
|
|
(*aux).binary.right = right;
|
|
|
|
|
|
|
|
return aux;
|
|
|
|
}
|
|
|
|
|
|
|
|
union expression* webdice_mul(union expression* left, union expression* right){
|
|
|
|
return webdice_binary(WEBDICE_MUL,left,right);
|
|
|
|
}
|
|
|
|
|
|
|
|
union expression* webdice_div(union expression* left, union expression* right){
|
|
|
|
return webdice_binary(WEBDICE_DIV,left,right);
|
|
|
|
}
|
|
|
|
|
|
|
|
union expression* webdice_add(union expression* left, union expression* right){
|
|
|
|
return webdice_binary(WEBDICE_ADD,left,right);
|
|
|
|
}
|
|
|
|
|
|
|
|
union expression* webdice_sub(union expression* left, union expression* right){
|
|
|
|
return webdice_binary(WEBDICE_SUB,left,right);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct expression_result resolve(union expression* root){
|
|
|
|
struct expression_result result,left,right;
|
|
|
|
|
|
|
|
int i, j;
|
|
|
|
int64_t *values = NULL;
|
|
|
|
int64_t total;
|
|
|
|
long double size;
|
|
|
|
int64_t length = 1;
|
|
|
|
|
|
|
|
switch((*root).id.id){
|
|
|
|
case WEBDICE_CONST:
|
|
|
|
size = log10l((*root).constant.value);
|
|
|
|
length += (int64_t) ceill(size);
|
|
|
|
result.min = (*root).constant.value;
|
|
|
|
result.max = (*root).constant.value;
|
|
|
|
result.expected = (*root).constant.value;
|
|
|
|
result.actual = (*root).constant.value;
|
|
|
|
result.text = (char*) malloc(length * sizeof(char));
|
|
|
|
sprintf(result.text, "%lld",(*root).constant.value);
|
|
|
|
break;
|
|
|
|
case WEBDICE_ROLL:
|
|
|
|
size = ((*root).roll.count + 1) * ceill(30+log10l((*root).roll.count * (*root).roll.type));
|
|
|
|
length += (int64_t) size;
|
|
|
|
result.min = (*root).roll.count;
|
|
|
|
result.max = (*root).roll.count * (*root).roll.type;
|
|
|
|
result.expected = (*root).roll.count * ((*root).roll.type + 1.0) / 2.0;
|
|
|
|
result.text = (char*) malloc(length * sizeof(char));
|
|
|
|
values = (int64_t*) malloc((*root).roll.count * sizeof(int64_t));
|
|
|
|
for (i = 0, j = (*root).roll.count, total = 0; i < (*root).roll.count; i++, j--){
|
|
|
|
values[i] = 1 + (rand() % (*root).roll.type);
|
|
|
|
total += values[i];
|
|
|
|
if (i == 0 && j == 1){
|
|
|
|
sprintf(result.text,"<span title=\"%lldd%lld=%lld\">%lld</span>", (*root).roll.count, (*root).roll.type, values[i], total);
|
|
|
|
}else if (i == 0){
|
|
|
|
sprintf(result.text,"<span title=\"%lldd%lld=%lld,", (*root).roll.count, (*root).roll.type, values[i]);
|
|
|
|
}else if (j == 1){
|
|
|
|
sprintf(&(result.text[strlen(result.text)]),"%lld\">%lld</span>", values[i], total);
|
|
|
|
}else{
|
|
|
|
sprintf(&(result.text[strlen(result.text)]),"%lld,", values[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(values);
|
|
|
|
result.actual = total;
|
|
|
|
break;
|
|
|
|
case WEBDICE_BINARY:
|
|
|
|
left = resolve((*root).binary.left);
|
|
|
|
right = resolve((*root).binary.right);
|
|
|
|
length += 5 + strlen(left.text) + strlen(right.text);
|
|
|
|
result.text = (char*) malloc(length * sizeof(char));
|
|
|
|
switch((*root).binary.operation){
|
|
|
|
case WEBDICE_MUL:
|
|
|
|
result.min = left.min * right.min;
|
|
|
|
result.max = left.max * right.max;
|
|
|
|
result.expected = left.expected * right.expected;
|
|
|
|
result.actual = left.actual * right.actual;
|
|
|
|
sprintf(result.text,"(%s * %s)",left.text,right.text);
|
|
|
|
break;
|
|
|
|
case WEBDICE_DIV:
|
|
|
|
result.min = left.min / right.max;
|
|
|
|
result.max = left.max / right.min;
|
|
|
|
result.expected = left.expected / right.expected;
|
|
|
|
result.actual = left.actual / right.actual;
|
|
|
|
sprintf(result.text,"(%s / %s)",left.text,right.text);
|
|
|
|
break;
|
|
|
|
case WEBDICE_ADD:
|
|
|
|
result.min = left.min + right.min;
|
|
|
|
result.max = left.max + right.max;
|
|
|
|
result.expected = left.expected + right.expected;
|
|
|
|
result.actual = left.actual + right.actual;
|
|
|
|
sprintf(result.text,"(%s + %s)",left.text,right.text);
|
|
|
|
break;
|
|
|
|
case WEBDICE_SUB:
|
|
|
|
result.min = left.min - right.max;
|
|
|
|
result.max = left.max - right.min;
|
|
|
|
result.expected = left.expected - right.expected;
|
|
|
|
result.actual = left.actual - right.actual;
|
|
|
|
sprintf(result.text,"(%s - %s)",left.text,right.text);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
free(result.text);
|
|
|
|
result.text = NULL;
|
|
|
|
result.min = 0;
|
|
|
|
result.max = 0;
|
|
|
|
result.expected = 0;
|
|
|
|
result.actual = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
free(left.text);
|
|
|
|
free(right.text);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
result.text = NULL;
|
|
|
|
result.min = 0;
|
|
|
|
result.max = 0;
|
|
|
|
result.expected = 0;
|
|
|
|
result.actual = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void free_expression(union expression* root){
|
|
|
|
switch((*root).id.id){
|
|
|
|
case WEBDICE_BINARY:
|
|
|
|
free_expression((*root).binary.left);
|
|
|
|
free_expression((*root).binary.right);
|
|
|
|
case WEBDICE_CONST:
|
|
|
|
case WEBDICE_ROLL:
|
|
|
|
default:
|
|
|
|
free(root);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|