#!/usr/intel/bin/perl

# Arithmetic 3 - adding and substituting numbers 1..20 and round numbers 10..100

use strict;
use Tk;
use Tk::Entry;
use Tk::Frame;
use Tk::Canvas;

my $mw=MainWindow->new(-title=>'Arithmetic for 6-7 years old');
my @right_value;
my @answer;
my @polygon=(
80.29,5.85,92.63,9.21,230.20,11.47,320.73,9.16,344.09,4.85,337.58,25.51,344.83,190.88,336.19,357.06,334.05,374.15,319.04,368.15,208.20,365.25,95.21,366.20,76.10,375.15,78.85,345.90,92.57,191.85,82.14,25.17);

my $c = $mw->Canvas(-width=>350,-height=>400
 )->pack(-side=>'top',-anchor=>'nw',-fill=>'both',-padx=>10,-pady=>10);

&new_game;

my $bot_fr = $mw->Frame()->pack(-fill=>'x',-side=>'bottom',-padx=>10,-pady=>10);
$bot_fr->Button(-text=>'Check',-command=>
  sub
  {
    $c->itemconfigure('key',-fill=>
     (join(' ',@answer) eq join(' ',@right_value))?'green':'yellow');
    $c->delete('mark');
    foreach my $i(0 .. $#answer)
    {
      next unless $answer[$i];
      if($answer[$i] == $right_value[$i])
      {
        $c->create('line',300,18+$i*54,309,47+$i*54,319,15+$i*54, 
          -fill=>'green',-width=>4,-tags=>['mark']);
      }
      else
      {
        $c->create('line',300,18+$i*54,317,47+$i*54,
          -fill=>'red',-width=>4,-tags=>['mark']);
        $c->create('line',303,45+$i*54,319,18+$i*54,
          -fill=>'red',-width=>4,-tags=>['mark']);
      }
    }
    animate_key($c)
      if(join(' ',@answer) eq join(' ',@right_value));
  }
)->pack(-side=>'left',-expand=>1);
$bot_fr->Button(-text=>'New game',-command=>\&new_game)->pack(-side=>'left',-expand=>1);
$bot_fr->Button(-text=>'Dismiss',-command=>sub{exit})->pack(-side=>'left',-expand=>1);

MainLoop;

sub new_game
{
@right_value=();
@answer=();
$c->delete('all');
$c->create('rectangle',18,7,35,159,-fill=>'yellow',-tags=>['key','draw']);
$c->create('polygon',
35.70,7,35.70,157,53.70,157,62.95,126.37,53.80,96.75,61.66,70.63,53.90,47.50,61.00,26.25,47.37,7,
 -outline=>'black',-fill=>'yellow',-tags=>['key','draw']);
$c->create('oval',2,137,79,217,-fill=>'yellow',-tags=>['key','draw']);
$c->create('oval',36,194,46,208,-fill=>'gray',-tags=>['draw']);

my @polygon_todraw=@polygon;

foreach my $count(0 .. 12)
{
  $polygon_todraw[rand($#polygon_todraw)] += rand(8)-4;
}

$c->create('polygon',
@polygon_todraw,
-fill=>'wheat2',-outline=>'Black',-smooth=>1);

foreach my $i(0 .. 5)
{
  # Generate random expression:
  # Expressions can be of 2 types
  # 1. Counting till 100 with steps of 1..9
  # ---+--------------|---->
  #    \_+4_/\_+6__/  |
  #            \_-3/  |
  #            \__+8__/
  # 2. Counting till 100 with round numbers
  # ---+--+---+---+---|---+--->
  #    
  my $type=(rand(100)>60)? 0 : 1;
  my $expression='';
  my @values;
  my $val;
  my $last_val=0;
  if($type) # regular numbers
  {
    foreach my $op_i(0 .. 3)
    {
      # if 1st number - just generate it
      if (! $op_i)
      {
        $val=&generate_int(19);
      }
      else
      # if other - generate random displacement
      {
        my $x;
        do
	{
          $x = &generate_int(9);
	  $x = -$x if (rand(100)>50);
	  $val = $last_val + $x;
	}
	while($val<=0 || $val>20 || grep($val==$_,@values) ||
          ($x<0 && $val<10 && $last_val>10));
        # Displacement must conform to following rules:
        # +/-(1..9)
        # do not exceed 0 and 100 limits after applying to last value
        # do not produce same value as stored in values history
      }
      $expression .= ' ' . ($val-$last_val);
      $expression =~ s/(\d) (\d)/$1 + $2/g;
      $expression =~ s/(\d) -(\d)/$1 - $2/g;
      $last_val=$val;
      push (@values,$val);
    }
    $last_val=eval $expression;
  }
  else # round numbers
  {
    foreach my $op_i(0 .. 3)
    {
      do { $val = &generate_int(10)*10; }
      while( grep($val == $_,@values));
      $expression .= ' ' . ($val-$last_val);
      $expression =~ s/(\d) (\d)/$1 + $2/g;
      $expression =~ s/(\d) -(\d)/$1 - $2/g;
      $last_val = $val;
      push(@values,$val);
    }
    $last_val=eval $expression;
  }
  push(@right_value,$last_val);
  my $column=0;
  foreach my $item(split(' ',$expression))
  {
    next unless $item;
    if($item=~/\d/)
    {
      $c->create('text',100+$column*20,40+$i*54,-anchor=>'n',-text=>$item);
    }
    else
    {
      $c->create('text',100+$column*20,40+$i*54,-anchor=>'n',-text=>$item);
      if($column<=4)
      {
        my $e=$c->Entry(-width=>2);
        $c->create('window',100+$column*20,18+$i*54,-anchor=>'n',-window=>$e);
      }
    }
    $column++;
  }
  $c->create('text',100+$column*20,40+$i*54,-anchor=>'n',-text=>'=');
  my $entry=$c->Entry(-justify=>'center',-width=>4,-textvariable=>\($answer[$i]));
  $c->create('window',250,40+$i*54,-window=>$entry,-anchor=>'nw');
}
}

sub generate_int
{
   return int(1+rand(shift()-1))
}

sub animate_key
{
  my ($c)=(@_);
  # draw rotating key animation
  Tk::DoOneEvent(0);
  $mw->after(1000);
  Tk::DoOneEvent(0);
  foreach my $i(0 .. 18)
  {
    $mw->after(80);
    Tk::DoOneEvent(0);
    $c->delete('draw');
    $c->create('line',
      43-cos($i*10*3.1415926/180)*43,43-sin($i*10*3.1415926/180)*43,
      43+cos($i*10*3.1415926/180)*43,43+sin($i*10*3.1415926/180)*43,
      -fill=>'lightgreen',-width=>6,-tags=>['draw']);
  }
}
