/*
is based on sm09_e39.gsz.
Changes:

- a global variable nbleaves for the total number of leaves is
  introduced.
- Three maturity classes for leaves are introduced, with different
  growth rates.
- The growth parameters of these 3 classes are specified in arrays.

*/

// internode with small start size:
module Internode(int age, int lnfb) extends F(0.01, 0.0005)
{{ setShader(GREEN); }};

// a meristem as seed for growth:
module Meristem(int age, int lnfb) extends Sphere(0.0005)
{{ setShader(RED); }};

// the petiole:
module Petiole(int age, int lnfb) extends F(0.001, 0.0001)
{{ setShader(GREEN); }};

// the leaf:
module Blade(int age, int lnfb) extends Parallelogram(1.0, 1.0/1.3);

const Shader leafmat = shader ("Leaf1");

public int time = 0;        // time unit = one hour
public int nbleaves = 0;    // total number of all leaves

const int PLASTOCHRON = 48; // number of time units between the
                            // emergence of two leaves
const int MAX_GROWTHTIME_INTERNODE = 60;
const int MAX_GROWTHTIME_PETIOLE = 30;
const int MAX_GROWTHTIME_LEAF = 96;

const float GROWTH_RATE_INTERNODE_LENGTH = 0.001;
const float GROWTH_RATE_INTERNODE_DIAMETER = 0.000004;
const float GROWTH_RATE_PETIOLE_LENGTH = 0.00117;
const float GROWTH_RATE_PETIOLE_DIAMETER = 0.000031;
const float GROWTH_RATE_LEAF_SCALE = 0.0016;

const int NEWLEAF = 0;      // three maturity classes
const int MATURELEAF = 1;
const int OVERMATURELEAF = 2;

const float[] MAX_GWROWTH_INTERNODE = {0.03, 0.05, 0.04};
const float[] MAX_GWROWTH_PETIOLE = {0.01, 0.07, 0.02};
const float[] MAX_GWROWTH_LEAF_SCALE = {0.04, 0.09, 0.03};


protected void init()
{
   time = 0;
   nbleaves = 0;
   [
   Axiom ==> Meristem(0, 0);
   ]
}

public void run()
{
   time++;
   println("Hour:" + time);
   [   
   // first rule: the meristem ages
   m:Meristem ::> m[age]++;	
	
   // for a meristem: formation of the internode
   m:Meristem, (m[age] == PLASTOCHRON || m[lnfb] == 0) ==> 
      Internode(0, m[lnfb]+1) [ RL(45) Petiole(0, m[lnfb]+1) 
      RH(5) RL(30) 
      [ Blade(0, m[lnfb]+1).(setShader(leafmat), setScale(0.001))
         { nbleaves ++; }               // new leaf is counted!
      ] ] RH(140) RU(random(-5,5)) Meristem(0, m[lnfb]+1);
   ]

   [  
   // block for internode extension:
   i:Internode ::> 
      {
      int maturityclass = 0;
      int lpi = nbleaves - i[lnfb] - 1;   // leaf age
      if (lpi < 3) 
         { maturityclass = 1; } 
      else 
         { 
         if (i[lnfb] > 5 )
            { maturityclass = 2; }
         else 
            { maturityclass = 3; }
         }
      if (i[age] <  MAX_GROWTHTIME_INTERNODE && 
         i[length] <= MAX_GWROWTH_INTERNODE[maturityclass-1]) 
         { i[length] += GROWTH_RATE_INTERNODE_LENGTH; }  // length growth
                                                         // during firs days
      i[diameter] += GROWTH_RATE_INTERNODE_DIAMETER;   // diam. growth always
      i[age]++; // age increment
      }
   ]

   [  
   // block for petiole extension during the first days:
   p:Petiole, (p[age] < MAX_GROWTHTIME_PETIOLE) ::> 
      {
      p[length] += GROWTH_RATE_PETIOLE_LENGTH;     // length growth
      p[diameter] += GROWTH_RATE_PETIOLE_DIAMETER; // diameter growth
      p[age]++;                           // age increment
      }
   ]

   [ 
   // block for leaf growth:
   s:Blade, (s[age] < MAX_GROWTHTIME_LEAF) ::> 
      {
      s.setScale(s[scale] + GROWTH_RATE_LEAF_SCALE);
      s[age]++;
      }
   ]
}

