Fixed typos

Fixed typos

contract Master
{
  //Initialize master data store
  mapping (address => uint) tokenBalance;
  mapping (address => string) tagName;
  mapping (string => address) tagAddressFromName;
  mapping (address => address[]) achievements;

  function Master()
  {

  }

  function mapTokenBalance(address a, uint b)
  {
    tokenBalance[a] = b;
  }
  function mapTagName(address a, string n)
  {
    tagName[a] = n;
  }
  function mapTagAddressFromName(string n, address a)
  {
    tagAddressFromName[n] = a;
  }
  function mapAchievement(address a, address t)
  {
    achievements[a].push(t);
  }
  function getTokenBalance(address a) returns(uint)
  {
    return tokenBalance[a];
  }
  function getTagName(address a) returns(string)
  {
    return tagName[a];
  }
  function getTagAddressFromName(string n) returns(address)
  {
    return tagAddressFromName[n];
  }
  function getAchievement(address a) returns(address[])
  {
    return achievements[a];
  }
  function getNumberOfachievments(address a) returns(uint)
  {
    return achievments[a].length;
  }

  function addTag(string name, address[] parentList) returns(uint) //Creates a new tag contract
  {
    uint response = 0;
    if(tokenBalance[msg.sender] < 1)
    {
      response += 1;
    }
    if(tagAddressFromName[name] == 0)
    {
      response += 10;
    }
    if(response==0)
    {
      Tag newTag = new Tag();
      address newTagAddress = address(newTag);
      tagName[newTagAddress] = name;
      tagAddressFromName[name] = newTagAddress;

      for(uint i=0; i<= parentList.length; i++) //adds all the given parents
      {
        if(parentList[i]==0)
        {
          response += 100;
        }
        if(response==0)
        {
          newTag.addParent(parentList[i]);
        }
      }
    }
    newTag.setMaster(address(this));
    newTag.setName(name);
    return response;
  }
}

//Defines the meta-contract for a Tag
contract Tag
{
  address[] parentTags;
  address master;
  string name;
  address[] owners; //Those who have earned the tag
  mapping(address => address[]) assessmentHistory; //All assessments completed
  mapping(address => uint) scores; //All positive assessements scores

  function Tag()
  {

  }

  function addParent(address parentTag)
  {
    parentTags.push(parentTag);
  }

  function setMaster(address m)
  {
    master = m;
  }

  function setName(string n)
  {
    name = n;
  }

  function setAssessorPool(address a, address assessment)
  {
    for(uint i = 0; i < Tag(a).owners.length && Assessment(assessment).poolSizeRemaining != 0; i++)
    {
      if(pool.length < .1*Tag(a).owners.length)
      {
        Assessment(assessment).addToAssessorPool(Tag(a).owners[getRandom(Tag(a).owners.length)]);
        Assessment(assessment).poolSizeRemaining--;
      }
      else
      {
        for(uint j = 0; j < Tag(a).parentTags.length; j++)
        {
          setAssessorPool(s, Tag(a).parentTags[j], assessment);
        }
      }
      if(Assessment(assessment).poolSizeRemaining =< 0)
      {
        Assessment(assessment).setAssessors();
      }
    }
  }

  function startAssessment(address assessee, uint size)
  {
    Assessment newAssessment;
    newAssessment.setAssessee(assessee);
    newAssessment.setTag(address(this));
    newAssessment.setNumberOfAssessors(size);
    newAssessment.setAssessmentPoolSize(size*20)
    setAssessorPool(address(this), address(newAssessment));
  }

  function finishAssessment(bool result, uint score, address assessee, address assessment) returns(bool)
  {
    if(result == true)
    {
      owners.push(assessee);
      scores[assessee] = score;
      Master(master).mapachievment(assessee,address(this));
    }
    assessmentHistory[assessee].push(assessment);
    return result;
  }
}

//Defines the meta-contract for an assessment
contract Assessment
{
  address assessee; //We need a better word for this
  address[] assessorPool;
  address[] assessors;
  address tag;
  uint poolSizeRemaining;
  uint numberOfAssessors;
  struct Results
  {
    bool pass;
    uint score;
  }
  mapping(address => uint[]) assessmentQuestions; //Given by the assessors as IPFS hashes
  mapping(address => uint[]) assessmentAnswers; //Given by the assessee as IPFS hashes
  mapping(address => Results) assessmentResults; //Pass/Fail and Score given by assessors
  uint finalScore;
  bool finalResult;

  function Assessment()
  {

  }

  function setAssessee(address newAssessee)
  {
    assessee = newAssessee;
  }

  function setNumberOfAssessors(uint n)
  {
    numberOfAssessors = n;
  }

  function setAssessmentPoolSize(uint n)
  {
    poolSizeRemaining = n;
  }
  function addToAssessorPool(address a)
  {
    assessorPool.push(a);
  }

  function setAssessors()
  {
    for(uint i = 0, i < n, i++)
    {
      assessors.push(assessorPool[getRandom(assessorPool.length)]);
    }
  }

  function setTag(address t)
  {
    tag = t;
  }

  function setQuestion(address a, uint[] data)
  {
    assessmentQuestions[a] = data;
  }

  function getQuestion(address a) returns(uint[])
  {
    return assessmentQuestions[a];
  }

  function setAnswer(address a, uint[] data)
  {
    assessmentAnswers[a] = data;
  }

  function getAnswer(address a) returns(uint[])
  {
    return assessmentAnswers[a];
  }

  function setResult(address a, bool b, uint s)
  {
    Results memory results;
    results.pass = b;
    results.score = s;
    assessmentResults[a] = results;
  }

  function assess()
  {

  }

  function calculateResult()
  {

  }

  function returnResults()
  {
    Tag(tag).finishAssessment(finalResult, finalScore, assessee, address(this));
  }

  function cashout()
  {

  }
}

contract Master
{
  //Initialize master data store
  mapping (address => uint) tokenBalance;
  mapping (address => string) tagName;
  mapping (string => address) tagAddressFromName;
  mapping (address => address[]) acheivements;

  function Master()
  {

  }

  function mapTokenBalance(address a, uint b)
  {
    tokenBalance[a] = b;
  }
  function mapTagName(address a, string n)
  {
    tagName[a] = n;
  }
  function mapTagAddressFromName(string n, address a)
  {
    tagAddressFromName[n] = a;
  }
  function mapAcheivement(address a, address t)
  {
    acheivements[a].push(t);
  }
  function getTokenBalance(address a) returns(uint)
  {
    return tokenBalance[a];
  }
  function getTagName(address a) returns(string)
  {
    return tagName[a];
  }
  function getTagAddressFromName(string n) returns(address)
  {
    return tagAddressFromName[n];
  }
  function getAcheivement(address a) returns(address[])
  {
    return acheivements[a];
  }
  function getNumberOfAcheivements(address a) returns(uint)
  {
    return acheivements[a].length;
  }

  function addTag(string name, address[] parentList) returns(uint) //Creates a new tag contract
  {
    uint response = 0;
    if(tokenBalance[msg.sender] < 1)
    {
      response += 1;
    }
    if(tagAddressFromName[name] == 0)
    {
      response += 10;
    }
    if(response==0)
    {
      Tag newTag = new Tag();
      address newTagAddress = address(newTag);
      tagName[newTagAddress] = name;
      tagAddressFromName[name] = newTagAddress;

      for(uint i=0; i<= parentList.length; i++) //adds all the given parents
      {
        if(parentList[i]==0)
        {
          response += 100;
        }
        if(response==0)
        {
          newTag.addParent(parentList[i]);
        }
      }
    }
    newTag.setMaster(address(this));
    newTag.setName(name);
    return response;
  }
}

//Defines the meta-contract for a Tag
contract Tag
{
  address[] parentTags;
  address master;
  string name;
  address[] owners; //Those who have earned the tag
  mapping(address => address[]) assessmentHistory; //All assessments completed
  mapping(address => uint) scores; //All positive assessements scores

  function Tag()
  {

  }

  function addParent(address parentTag)
  {
    parentTags.push(parentTag);
  }

  function setMaster(address m)
  {
    master = m;
  }

  function setName(string n)
  {
    name = n;
  }

  function setAssessorPool(address a, address assessment)
  {
    for(uint i = 0; i < Tag(a).owners.length && Assessment(assessment).poolSizeRemaining != 0; i++)
    {
      if(pool.length < .1*Tag(a).owners.length)
      {
        Assessment(assessment).addToAssessorPool(Tag(a).owners[getRandom(Tag(a).owners.length)]);
        Assessment(assessment).poolSizeRemaining--;
      }
      else
      {
        for(uint j = 0; j < Tag(a).parentTags.length; j++)
        {
          setAssessorPool(s, Tag(a).parentTags[j], assessment);
        }
      }
      if(Assessment(assessment).poolSizeRemaining =< 0)
      {
        Assessment(assessment).setAssessors();
      }
    }
  }

  function startAssessment(address assessee, uint size)
  {
    Assessment newAssessment;
    newAssessment.setAssessee(assessee);
    newAssessment.setTag(address(this));
    newAssessment.setNumberOfAssessors(size);
    newAssessment.setAssessmentPoolSize(size*20)
    setAssessorPool(address(this), address(newAssessment));
  }

  function finishAssessment(bool result, uint score, address assessee, address assessment) returns(bool)
  {
    if(result == true)
    {
      owners.push(assessee);
      scores[assessee] = score;
      Master(master).mapAcheivement(assessee,address(this));
    }
    assessmentHistory[assessee].push(assessment);
    return result;
  }
}

//Defines the meta-contract for an assessment
contract Assessment
{
  address assessee; //We need a better word for this
  address[] assessorPool;
  address[] assessors;
  address tag;
  uint poolSizeRemaining;
  uint numberOfAssessors;
  struct Results
  {
    bool pass;
    uint score;
  }
  mapping(address => uint[]) assessmentQuestions; //Given by the assessors as IPFS hashes
  mapping(address => uint[]) assessmentAnswers; //Given by the assessee as IPFS hashes
  mapping(address => Results) assessmentResults; //Pass/Fail and Score given by assessors
  uint finalScore;
  bool finalResult;

  function Assessment()
  {

  }

  function setAssessee(address newAssessee)
  {
    assessee = newAssessee;
  }

  function setNumberOfAssessors(uint n)
  {
    numberOfAssessors = n;
  }

  function setAssessmentPoolSize(uint n)
  {
    poolSizeRemaining = n;
  }
  function addToAssessorPool(address a)
  {
    assessorPool.push(a);
  }

  function setAssessors()
  {
    for(uint i = 0, i < n, i++)
    {
      assessors.push(assessorPool[getRandom(assessorPool.length)]);
    }
  }

  function setTag(address t)
  {
    tag = t;
  }

  function setQuestion(address a, uint[] data)
  {
    assessmentQuestions[a] = data;
  }

  function getQuestion(address a) returns(uint[])
  {
    return assessmentQuestions[a];
  }

  function setAnswer(address a, uint[] data)
  {
    assessmentAnswers[a] = data;
  }

  function getAnswer(address a) returns(uint[])
  {
    return assessmentAnswers[a];
  }

  function setResult(address a, bool b, uint s)
  {
    Results memory results;
    results.pass = b;
    results.score = s;
    assessmentResults[a] = results;
  }

  function assess()
  {

  }

  function calculateResult()
  {

  }

  function returnResults()
  {
    Tag(tag).finishAssessment(finalResult, finalScore, assessee, address(this));
  }

  function cashout()
  {

  }
}


Finished commenting the master.

Finished commenting the master.

contract Creator
{
  address masterAddress;

  /*
  @type: event
  @name: TagCreation
  @occasion: When a tag is created
  @purpose: To help build a data store of tags
  @stores: string _tagName = the name of the tag that was created
  @stores: address _tagAddress = the address of the tag that was created
  @stores: address[] _parents = the addresses of the parents of the tag that as created
  */
  event TagCreation
  ( string _tagName,
    address _tagAddress,
    address[] _parents);

  function Creator()
  {
    Master master = new Master(address(this));
    masterAddress = address(master);
  }

  function addUser()
  {
    User newUser = new User(msg.sender, masterAddress);
    Tag(Master(masterAddress).getTagAddressFromName("account")).startAssessment(address(newUser),5, 600);
  }

  function addTag(string name, address[] parentList) returns(uint) //Creates a new tag contract
  {
    uint response = 0;
    address[] memory parents;
    if(Master(masterAddress).getTokenBalance(msg.sender) < 1)
    {
      response += 1;
    }
    if(Master(masterAddress).getTagAddressFromName(name) != 0)
    {
      response += 10;
    }
    if(response==0)
    {
      for(uint i=0; i<= parentList.length; i++) //adds all the given parents
      {
        if(parentList[i]==0)
        {
          response += 100*(10**i);
        }
        else
        {
          parents[i] = parentList[i];
        }
      }
      Tag newTag = new Tag(name, parents, masterAddress);
      address newTagAddress = address(newTag);
      Master(masterAddress).mapTagName(newTagAddress,name);
      Master(masterAddress).mapTagAddressFromName(name,newTagAddress);
      Master(masterAddress).mapTokenBalance(msg.sender,Master(masterAddress).getTokenBalance(msg.sender) - 1);
      TagCreation(name, newTagAddress, parents);
    }
    return response;
  }
}

/*
@type: contract
@name: Master
@purpose: To store data for easy and secure access
*/
contract Master
{
  address creatorAddress; //The address of the Creator contract
  mapping (address => uint) tokenBalance; //Maps the addresses of users to their token balances
  mapping (address => string) tagName; //Maps the address of tags to their names
  mapping (string => address) tagAddressFromName; //Maps the names of tags to their addresses
  mapping (address => address[]) achievements; //Maps the addresses of users to an array of addresses that contain the addresses of the tags that they have passed an assessment in
  mapping (address => bool) availability; //Maps the addresses of users to their availability status for whether or not they can currently assess someone
  mapping (address => address) users; //Maps the addresses of the users to their actual location of the blockchain

  /*
  @type: constructer function
  @purpose: To initialize the master contract and have it make the account tag
  @param: none
  @returns: nothing
  */
  function Master(address creator)
  {
    creatorAddress = creator; //Sets the address of the Creator contract
    tokenBalance[address(this)] = 1; //Gives the master contract a temporary tokenBalance so that it may make the tag
    address[] memory a; //Makes an empty array to serve as the parents of the tag
    uint useless = Creator(creatorAddress).addTag("account", a); //creates the account tag and gives the value of its error code to a relatively useless uint
  }

  /*
  @type: function
  @purpose: To set a new token balance for a user
  @param: address user = the address of the user whose token balance is to be mapped
  @param: uint balance = the new token balance for the user
  @returns: nothing
  */
  function mapTokenBalance(address user, uint balance)
  {
    if(tagAddressFromName[tagName[msg.sender]] == 0) //makes sure this function is not called by a tag
    {
      tokenBalance[user] = balance; //sets the token balance of the user
    }
  }

  /*
  @type: function
  @purpose: To map the name of a tag to its address
  @param: address tagAddress = the address of the tag being mapped
  @param: string name = the name of the tag being mapped
  @return: nothing
  */
  function mapTagName(address tagAddress, string name)
  {
    tagName[tagAddress] = name; //maps the name of the tag to its address
  }

  /*
  @type: function
  @purpose: To map the address of a tag to its name
  @param: string name = the name of the tag being mapped
  @param: address tagAddress = the address of the tag being mapped
  @returns: nothing
  */
  function mapTagAddressFromName(string name, address tagAddress)
  {
    tagAddressFromName[name] = tagAddress; //maps the address of the tag to its name
  }

  /*
  @type: function
  @purpose: To map the address of a user to the address of the tag that the user has just passed
  @param: address user = the address of the user
  @param: address acheivment = the address of the tag just passed
  @returns: nothing
  */
  function mapAchievement(address user, address achievment)
  {
    achievements[user].push(achievment); //adds the address of the tag to the end of the array that is mapped to the user
  }

  /*
  @type: function
  @purpose: To map the user's availability to assess to the user's address
  @param: address user = the address of the user
  @param: bool available = the availa status of the user to assess
  @returns: nothing
  */
  function mapAvailability(address user, bool available)
  {
    availability[user] = available;
  }

  /*
  @type: function
  @purpose: To get the user's token balance
  @param: address user = the address of the user
  @returns: The token balance in the form of a uint
  */
  function getTokenBalance(address user) returns(uint)
  {
    return tokenBalance[user];
  }

  /*
  @type: function
  @purpose: To get the name of a tag from its address
  @param: address tagAddress = the address of the tag
  @returns: The name of the tag in the form of a string
  */
  function getTagName(address tagAddress) returns(string)
  {
    return tagName[tagAddress];
  }

  /*
  @type: function
  @purpose: To get the address of a tag from its name
  @param: string name = the name of the tag
  @returns: The address of the tag in the form of an address
  */
  function getTagAddressFromName(string name) returns(address)
  {
    return tagAddressFromName[name];
  }

  /*
  @type: function
  @purpose: To get the addresses of the tags that the user has achieved
  @param: address user = the address of the user
  @returns: The addresses of the tags that the user has achieved in the form of an array of addresses
  */
  function getAchievement(address user) returns(address[])
  {
    return achievements[user];
  }

  /*
  @type: function
  @purpose: To get the number of achievments of a user
  @param: address user = the address of the user
  @returns: The number of achievments of a user in the form of a uint
  */
  function getNumberOfachievments(address user) returns(uint)
  {
    return achievements[user].length;
  }

  /*
  @type: function
  @purpose: To get the availab of a user to assess
  @param: address user = the address of the user
  @returns: The availability of a user to assess in the form of a bool
  */
  function getAvailability(address user) returns(bool)
  {
    return availability[user];
  }
}

//Defines the meta-contract for a Tag
contract Tag
{
  address[] parentTags;
  address master;
  string name;
  string description;
  address[] owners; //Those who have earned the tag
  mapping(address => address[]) assessmentHistory; //All assessments completed
  mapping(address => int) scores; //All assessements scores
  event CompletedAssessment
  ( address _assessee,
    bool _pass,
    int _score,
    address _assessment);

  function Tag(string tagName, address[] parents, address masterAddress)
  {
    name = tagName;
    parentTags = parents;
    master = masterAddress;
  }

  function getDescription() returns(string)
  {
    return description;
  }

  function getOwners() returns(address[])
  {
    return owners;
  }

  function getOwnerLength() returns(uint)
  {
    return owners.length;
  }

  function getOwner(uint index) returns(address)
  {
    return owners[index];
  }

  function getParents() returns(address[])
  {
    return parentTags;
  }

  function getParentsLength() returns(uint)
  {
    return parentTags.length;
  }

  function getParent(uint index) returns(address)
  {
      return parentTags[index];
  }

  function setAssessorPool(address tagAddress, address assessment)
  {
    for(uint i = 0; i < Tag(tagAddress).getOwnerLength() && Assessment(assessment).getAssessmentPoolSize() != 0; i++)
    {
      if(Assessment(assessment).getAssessorPoolLength() < Tag(tagAddress).getOwnerLength()/10)
      {
        address random = Tag(tagAddress).getOwner(getRandom(Tag(tagAddress).getOwnerLength()-1));
        if(Master(master).getAvailability(random) == true)
        {
          Assessment(assessment).addToAssessorPool(random);
          Assessment(assessment).setAssessmentPoolSize(Assessment(assessment).getAssessmentPoolSize() -1);
        }
      }
      else
      {
        for(uint j = 0; j < Tag(tagAddress).getParentsLength(); j++)
        {
          setAssessorPool(Tag(tagAddress).getParent(j), assessment);
        }
      }
      if(Assessment(assessment).getAssessmentPoolSize() <= 0)
      {
        Assessment(assessment).setPotentialAssessor();
      }
    }
  }

  function startAssessment(address assessee, uint size, uint timeForSettingTask)
  {
    Assessment newAssessment = new Assessment(assessee, address(this), master, timeForSettingTask);
    newAssessment.setNumberOfAssessors(size);
    newAssessment.setAssessmentPoolSize(size*20);
    setAssessorPool(address(this), address(newAssessment));
  }

  function finishAssessment(bool pass, int score, address assessee, address assessment)
  {
    if(pass == true)
    {
      owners.push(assessee);
      scores[assessee] = score;
      Master(master).mapAchievement(assessee,address(this));
    }
    if(pass == false && address(this) == Master(master).getTagAddressFromName("account"))
    {
      User(assessee).remove();
    }
    assessmentHistory[assessee].push(assessment);
    CompletedAssessment(assessee, pass, score, assessment);
  }
  function getRandom(uint i) returns(uint)
  {
    return 12;
  }
}

//Defines the meta-contract for an assessment
contract Assessment
{
  address assessee; //We need a better word for this
  address[] assessorPool;
  mapping (address => uint) assessors;
  address[] finalAssessors;
  address tag;
  address master;
  uint poolSizeRemaining;
  uint numberOfAssessors;
  mapping(address => string) assessmentTasks; //Given by the assessors as IPFS hashes
  mapping(address => string) assessmentResponses; //Given by the assessee as IPFS hashes
  mapping(address => int) assessmentResults; //Pass/Fail and Score given by assessors
  mapping(int => address) addressFromScore;
  mapping(int => bool) inRewardCluster;
  address currentAssessor;
  int finalScore;
  bool finalResult;
  uint taskCreationTime;
  uint taskCompletionTime;
  uint taskGradingTime;
  uint referenceTime;
  uint numberCancelled;

  function Assessment(address assesseeAddress, address tagAddress, address masterAddress, uint timeForTaskCreation)
  {
    assessee = assesseeAddress;
    tag = tagAddress;
    master = masterAddress;
    referenceTime = block.timestamp;
    taskCreationTime = timeForTaskCreation;
  }

  function getTaskCreationTime() returns(uint)
  {
      return taskCreationTime;
  }

  function getTaskCompletionTime() returns(uint)
  {
      return taskCompletionTime;
  }

  function setNumberOfAssessors(uint number)
  {
    numberOfAssessors = number;
  }

  function getNumberOfAssessors() returns(uint)
  {
    return numberOfAssessors;
  }

  function setAssessmentPoolSize(uint sizeRemaining)
  {
    poolSizeRemaining = sizeRemaining;
  }

  function getAssessmentPoolSize() returns(uint)
  {
    return poolSizeRemaining;
  }

  function addToAssessorPool(address potentialAddress)
  {
    assessorPool.push(potentialAddress);
  }

  function setPotentialAssessor()
  {
    bool potentialAssessorSet = false;
    while(potentialAssessorSet == false)
    {
      address randomAssessor = assessorPool[getRandom(assessorPool.length)];
      if(assessors[randomAssessor] == 0)
      {
        assessors[randomAssessor] = 3;
        currentAssessor = randomAssessor;
        potentialAssessorSet = true;
        User(randomAssessor).notification("Called As A Potential Assessor",tag, 1);
      }
    }
    referenceTime = now;
  }

  function getAssessorPoolLength() returns(uint)
  {
      return assessorPool.length;
  }

  function getRandom(uint i) returns(uint)
  {
    return 12;
  }

  function setTask(string data, uint timeLimit)
  {
    if(numberCancelled >= numberOfAssessors)
    {
      cancelAssessment();
    }
    if(assessors[currentAssessor] == 5 && now - referenceTime <= taskCreationTime)
    {
      assessmentTasks[currentAssessor] = data;
      taskCompletionTime = timeLimit;
      assessors[currentAssessor] = 6;
      User(currentAssessor).notification("Task Data Inputted", tag, 5);
      User(assessee).notification("New Task Available", tag, 7);
      referenceTime = now;
    }
    if(now - referenceTime > taskCreationTime && assessors[currentAssessor]!=5)
    {
      User(currentAssessor).notification("Did Not Submit Task On Time", tag, 6);
      Master(master).mapTokenBalance(currentAssessor, Master(master).getTokenBalance(currentAssessor) - 1);
      User(currentAssessor).setReputation(User(currentAssessor).getReputation() + 1);
      numberCancelled++;
      setPotentialAssessor();
    }
  }

  function cancelAssessment()
  {
    User(assessee).notification("Assessment Cancled", tag, 8);
    for(uint i = 0; i < finalAssessors.length; i++)
    {
      User(finalAssessors[i]).notification("Assessment Cancled", tag, 8);
    }
    suicide(master);
  }

  function getTask(address assessorAddress) returns(string)
  {
    return assessmentTasks[assessorAddress];
  }

  function setResponse(string data)
  {
    if(assessors[currentAssessor] == 6 && now - referenceTime <= taskCompletionTime)
    {
      assessmentResponses[currentAssessor] = data;
      assessors[currentAssessor] = 7;
      User(currentAssessor).notification("Task Response Inputted", tag, 10);
      taskGradingTime = (3*(now - referenceTime))/2;
      referenceTime = now;
    }
    if(now - referenceTime > taskCompletionTime && assessors[currentAssessor]!=6)
    {
      User(assessee).notification("Did Not Submit Task Response On Time", tag, 11);
      Master(master).mapTokenBalance(currentAssessor, Master(master).getTokenBalance(assessee) - 1);
      cancelAssessment();
    }
  }

  function getResponse(address assesseeAddress) returns(string)
  {
    return assessmentResponses[assesseeAddress];
  }

  function setResult(int score)
  {
    if(numberCancelled >= numberOfAssessors)
    {
      cancelAssessment();
    }
    if(assessors[currentAssessor] == 7 && now - referenceTime <= taskGradingTime)
    {
      assessmentResults[currentAssessor] = score;
      addressFromScore[score] = currentAssessor;
      User(assessee).notification("Task Result Inputted", tag, 12);
      finalAssessors.push(currentAssessor);
    }
    if(now - referenceTime <= taskGradingTime && assessors[currentAssessor] != 7)
    {
      User(currentAssessor).notification("Did Not Submit Task Results On Time", tag, 13);
      User(assessee).notification("Assessor Has Not Graded In Time", tag, 14);
      Master(master).mapTokenBalance(currentAssessor, Master(master).getTokenBalance(assessee) - 1);
      User(currentAssessor).setReputation(User(currentAssessor).getReputation() + 1);
      numberCancelled++;
      setPotentialAssessor();
    }
    if(finalAssessors.length == numberOfAssessors)
    {
      calculateResult();
    }
    if(finalAssessors.length < numberOfAssessors)
    {
      setPotentialAssessor;
    }
  }

  function calculateMAD(int[] scores, int n) returns(int)
  {
    int meanScore;
    int totalRelativeDistance;
    int meanAbsoluteDeviation;
    for(uint j = 0; j < scores.length; j++)
    {
      meanScore += scores[j];
      inRewardCluster[scores[j]] = false;
    }
    meanScore /= n;
    for(uint k = 0; k < scores.length; k++)
    {
      int distanceFromMean = scores[k] - meanScore;
      if(distanceFromMean < 0)
      {
        distanceFromMean *= -1;
      }
      totalRelativeDistance += distanceFromMean;
    }
    meanAbsoluteDeviation = totalRelativeDistance/n;
  }

  function calculateResult()
  {
    int[][] memory clusters;
    int[] memory scores;
    uint n = 0;
    uint largestClusterIndex = 0;
    int averageScore;
    for(uint i = 0; i < numberOfAssessors; i++)
    {
      scores[i] = assessmentResults[finalAssessors[i]];
    }
    int meanAbsoluteDeviation = calculateMAD(scores,int(numberOfAssessors));
    for(uint l = 0; l < scores.length; l++)
    {
      for(uint m = 0; m < scores.length; m++)
      {
        n = 0;
        if(scores[l] - scores[m] <= meanAbsoluteDeviation)
        {
          clusters[l][n] = (scores[m]);
          n++;
        }
      }
      if(clusters[l].length > clusters[largestClusterIndex].length)
      {
        largestClusterIndex = l;
      }
    }
    for(uint o = 0; o < clusters[largestClusterIndex].length; n++)
    {
      averageScore += clusters[largestClusterIndex][o];
      inRewardCluster[clusters[largestClusterIndex][o]] = true;
    }
    averageScore /= int(clusters[largestClusterIndex].length);
    finalScore = averageScore;
    if(averageScore > 0)
    {
      finalResult = true;
    }
    if(averageScore <= 0)
    {
      finalResult = false;
    }
    payout();
  }

  function confirmAssessor(uint confirm, bool timeKnow)
  {
    if(numberCancelled >= numberOfAssessors)
    {
      cancelAssessment();
    }
    if(assessors[currentAssessor] != 0 && now - referenceTime <= 180)
    {
      assessors[currentAssessor] = confirm;
      if(confirm == 1)
      {
        User(currentAssessor).notification("Confirmed As Potential Assessor", tag, 2);
        referenceTime = now;
      }
      if(confirm == 2 || confirm == 4)
      {
        User(currentAssessor).notification("Confirmed As Not Assessing", tag, 3);
        numberCancelled ++;
        setPotentialAssessor();
      }
      if(confirm == 5)
      {
        User(currentAssessor).notification("Confirmed As Assessing", tag, 9);
        referenceTime = now;
      }
    }
    if(now - referenceTime > 180)
    {
      if(timeKnow == false && assessors[currentAssessor]==3)
      {
      User(currentAssessor).notification("Did Not Respond In Time To Be Assessor", tag, 4);
      Master(master).mapTokenBalance(currentAssessor, Master(master).getTokenBalance(currentAssessor) - 1);
      setPotentialAssessor();
      }
      if(timeKnow == true && assessors[currentAssessor]==1)
      {
        User(currentAssessor).notification("Did Not Respond In Time To Be Assessor", tag, 4);
        setPotentialAssessor();
      }
    }
  }

  function returnResults()
  {
    Tag(tag).finishAssessment(finalResult, finalScore, assessee, address(this));
  }

  function payout()
  {
    for(uint i = 0; i < finalAssessors.length; i++)
    {
      int score = assessmentResults[finalAssessors[i]];
      int scoreDistance = ((score - finalScore)*100)/finalScore;
      if(scoreDistance < 0)
      {
        scoreDistance *= -1;
      }
      uint distance = uint(scoreDistance);
      if(inRewardCluster[score] == true)
      {
        Master(master).mapTokenBalance(finalAssessors[i], Master(master).getTokenBalance(finalAssessors[i]) + uint((500/(100 - scoreDistance))));
        User(finalAssessors[i]).notification("You Have Received Payment For Your Assessment", tag, 15);
      }
      if(inRewardCluster[score] == true)
      {
        Master(master).mapTokenBalance(finalAssessors[i], Master(master).getTokenBalance(finalAssessors[i]) - uint((500/(100 - scoreDistance))));
        User(finalAssessors[i]).notification("You Have Received A Fine For Your Assessment", tag, 16);
      }
    }
  }
}

contract User
{
  address user;
  address master;
  address[] acheivements;
  string userData;
  uint reputation;

  event Notification
  ( string _description,
    address _sender,
    address _user,
    address _tag,
    uint _code);

  function User(address userAddress, address masterAddress)
  {
    user = userAddress;
    master = masterAddress;
    reputation = 1;
  }

  function getReputation() returns(uint)
  {
    return reputation;
  }

  function setReputation(uint newReputation)
  {
    reputation = newReputation;
  }

  function notification(string description, address tag, uint code)
  {
    Notification(description, msg.sender, address(this), tag, code);
  }

  function setUserData(string hash)
  {
    userData = hash;
  }

  function getUserData() returns(string)
  {
    return userData;
  }

  function remove()
  {
    suicide(master);
  }
}

contract Creator
{
  address masterAddress;

  /*
  @type: event
  @name: TagCreation
  @occasion: When a tag is created
  @purpose: To help build a data store of tags
  @stores: string _tagName = the name of the tag that was created
  @stores: address _tagAddress = the address of the tag that was created
  @stores: address[] _parents = the addresses of the parents of the tag that as created
  */
  event TagCreation
  ( string _tagName,
    address _tagAddress,
    address[] _parents);

  function Creator()
  {
    Master master = new Master(address(this));
    masterAddress = address(master);
  }

  function addUser()
  {
    User newUser = new User(msg.sender, masterAddress);
    Tag(Master(masterAddress).getTagAddressFromName("account")).startAssessment(address(newUser),5, 600);
  }

  function addTag(string name, address[] parentList) returns(uint) //Creates a new tag contract
  {
    uint response = 0;
    address[] memory parents;
    if(Master(masterAddress).getTokenBalance(msg.sender) < 1)
    {
      response += 1;
    }
    if(Master(masterAddress).getTagAddressFromName(name) != 0)
    {
      response += 10;
    }
    if(response==0)
    {
      for(uint i=0; i<= parentList.length; i++) //adds all the given parents
      {
        if(parentList[i]==0)
        {
          response += 100*(10**i);
        }
        else
        {
          parents[i] = parentList[i];
        }
      }
      Tag newTag = new Tag(name, parents, masterAddress);
      address newTagAddress = address(newTag);
      Master(masterAddress).mapTagName(newTagAddress,name);
      Master(masterAddress).mapTagAddressFromName(name,newTagAddress);
      Master(masterAddress).mapTokenBalance(msg.sender,Master(masterAddress).getTokenBalance(msg.sender) - 1);
      TagCreation(name, newTagAddress, parents);
    }
    return response;
  }
}

/*
@type: contract
@name: Master
@purpose: To store data for easy and secure access
*/
contract Master
{
  address creatorAddress;
  mapping (address => uint) tokenBalance; //Maps the addresses of users to their token balances
  mapping (address => string) tagName; //Maps the address of tags to their names
  mapping (string => address) tagAddressFromName; //Maps the names of tags to their addresses
  mapping (address => address[]) achievements; //Maps the addresses of users to an array of addresses that contain the addresses of the tags that they have passed an assessment in
  mapping (address => bool) availability; //Maps the addresses of users to their availability status for whether or not they can currently assess someone
  mapping (address => address) users; //Maps the addresses of the users to their actual location of the blockchain

  /*
  @type: constructer function
  @purpose: To initialize the master contract and have it make the account tag
  @param: none
  @returns: nothing
  */
  function Master(address creator)
  {
    creatorAddress = creator;
    tokenBalance[address(this)] = 1; //Gives the master contract a temporary tokenBalance so that it may make the tag
    address[] memory a; //Makes an empty array to serve as the parents of the tag
    uint useless = Creator(creatorAddress).addTag("account", a); //creates the account tag and gives the value of its error code to a relatively useless uint
  }

  /*
  @type: function
  @purpose: To set a new token balance for a user
  @param: address user = the address of the user whose token balance is to be mapped
  @param: uint balance = the new token balance for the user
  @returns: nothing
  */
  function mapTokenBalance(address user, uint balance)
  {
    if(tagAddressFromName[tagName[msg.sender]] == 0) //makes sure this function is not called by a tag
    {
      tokenBalance[user] = balance; //sets the token balance of the user
    }
  }

  /*
  @type: function
  @purpose: To map the name of a tag to its address
  @param: address tagAddress = the address of the tag being mapped
  @param: string name = the name of the tag being mapped
  @return: nothing
  */
  function mapTagName(address tagAddress, string name)
  {
    tagName[tagAddress] = name; //maps the name of the tag to its address
  }

  /*
  @type: function
  @purpose: To map the address of a tag to its name
  @param: string name = the name of the tag being mapped
  @param: address tagAddress = the address of the tag being mapped
  @returns: nothing
  */
  function mapTagAddressFromName(string name, address tagAddress)
  {
    tagAddressFromName[name] = tagAddress; //maps the address of the tag to its name
  }

  /*
  @type: function
  @purpose: To map the address of a user to the address of the tag that the user has just passed
  @param: address user = the address of the user
  @param: address acheivment = the address of the tag just passed
  @returns: nothing
  */
  function mapAchievement(address user, address achievment)
  {
    achievements[user].push(achievment); //adds the address of the tag to the end of the array that is mapped to the user
  }

  /*
  @type: function
  @purpose: To map the user's availability to assess to the user's address
  @param: address user = the address of the user
  @param: bool available = the availa status of the user to assess
  */
  function mapAvailability(address user, bool available)
  {
    availability[user] = available;
  }

  function getTokenBalance(address user) returns(uint)
  {
    return tokenBalance[user];
  }
  function getTagName(address tagAddress) returns(string)
  {
    return tagName[tagAddress];
  }
  function getTagAddressFromName(string name) returns(address)
  {
    return tagAddressFromName[name];
  }
  function getAchievement(address user) returns(address[])
  {
    return achievements[user];
  }
  function getNumberOfachievments(address user) returns(uint)
  {
    return achievements[user].length;
  }
  function getAvailability(address user) returns(bool)
  {
    return availability[user];
  }
}

//Defines the meta-contract for a Tag
contract Tag
{
  address[] parentTags;
  address master;
  string name;
  string description;
  address[] owners; //Those who have earned the tag
  mapping(address => address[]) assessmentHistory; //All assessments completed
  mapping(address => int) scores; //All assessements scores
  event CompletedAssessment
  ( address _assessee,
    bool _pass,
    int _score,
    address _assessment);

  function Tag(string tagName, address[] parents, address masterAddress)
  {
    name = tagName;
    parentTags = parents;
    master = masterAddress;
  }

  function getDescription() returns(string)
  {
    return description;
  }

  function getOwners() returns(address[])
  {
    return owners;
  }

  function getOwnerLength() returns(uint)
  {
    return owners.length;
  }

  function getOwner(uint index) returns(address)
  {
    return owners[index];
  }

  function getParents() returns(address[])
  {
    return parentTags;
  }

  function getParentsLength() returns(uint)
  {
    return parentTags.length;
  }

  function getParent(uint index) returns(address)
  {
      return parentTags[index];
  }

  function setAssessorPool(address tagAddress, address assessment)
  {
    for(uint i = 0; i < Tag(tagAddress).getOwnerLength() && Assessment(assessment).getAssessmentPoolSize() != 0; i++)
    {
      if(Assessment(assessment).getAssessorPoolLength() < Tag(tagAddress).getOwnerLength()/10)
      {
        address random = Tag(tagAddress).getOwner(getRandom(Tag(tagAddress).getOwnerLength()-1));
        if(Master(master).getAvailability(random) == true)
        {
          Assessment(assessment).addToAssessorPool(random);
          Assessment(assessment).setAssessmentPoolSize(Assessment(assessment).getAssessmentPoolSize() -1);
        }
      }
      else
      {
        for(uint j = 0; j < Tag(tagAddress).getParentsLength(); j++)
        {
          setAssessorPool(Tag(tagAddress).getParent(j), assessment);
        }
      }
      if(Assessment(assessment).getAssessmentPoolSize() <= 0)
      {
        Assessment(assessment).setPotentialAssessor();
      }
    }
  }

  function startAssessment(address assessee, uint size, uint timeForSettingTask)
  {
    Assessment newAssessment = new Assessment(assessee, address(this), master, timeForSettingTask);
    newAssessment.setNumberOfAssessors(size);
    newAssessment.setAssessmentPoolSize(size*20);
    setAssessorPool(address(this), address(newAssessment));
  }

  function finishAssessment(bool pass, int score, address assessee, address assessment)
  {
    if(pass == true)
    {
      owners.push(assessee);
      scores[assessee] = score;
      Master(master).mapAchievement(assessee,address(this));
    }
    if(pass == false && address(this) == Master(master).getTagAddressFromName("account"))
    {
      User(assessee).remove();
    }
    assessmentHistory[assessee].push(assessment);
    CompletedAssessment(assessee, pass, score, assessment);
  }
  function getRandom(uint i) returns(uint)
  {
    return 12;
  }
}

//Defines the meta-contract for an assessment
contract Assessment
{
  address assessee; //We need a better word for this
  address[] assessorPool;
  mapping (address => uint) assessors;
  address[] finalAssessors;
  address tag;
  address master;
  uint poolSizeRemaining;
  uint numberOfAssessors;
  mapping(address => string) assessmentTasks; //Given by the assessors as IPFS hashes
  mapping(address => string) assessmentResponses; //Given by the assessee as IPFS hashes
  mapping(address => int) assessmentResults; //Pass/Fail and Score given by assessors
  mapping(int => address) addressFromScore;
  mapping(int => bool) inRewardCluster;
  address currentAssessor;
  int finalScore;
  bool finalResult;
  uint taskCreationTime;
  uint taskCompletionTime;
  uint taskGradingTime;
  uint referenceTime;
  uint numberCancelled;

  function Assessment(address assesseeAddress, address tagAddress, address masterAddress, uint timeForTaskCreation)
  {
    assessee = assesseeAddress;
    tag = tagAddress;
    master = masterAddress;
    referenceTime = block.timestamp;
    taskCreationTime = timeForTaskCreation;
  }

  function getTaskCreationTime() returns(uint)
  {
      return taskCreationTime;
  }

  function getTaskCompletionTime() returns(uint)
  {
      return taskCompletionTime;
  }

  function setNumberOfAssessors(uint number)
  {
    numberOfAssessors = number;
  }

  function getNumberOfAssessors() returns(uint)
  {
    return numberOfAssessors;
  }

  function setAssessmentPoolSize(uint sizeRemaining)
  {
    poolSizeRemaining = sizeRemaining;
  }

  function getAssessmentPoolSize() returns(uint)
  {
    return poolSizeRemaining;
  }

  function addToAssessorPool(address potentialAddress)
  {
    assessorPool.push(potentialAddress);
  }

  function setPotentialAssessor()
  {
    bool potentialAssessorSet = false;
    while(potentialAssessorSet == false)
    {
      address randomAssessor = assessorPool[getRandom(assessorPool.length)];
      if(assessors[randomAssessor] == 0)
      {
        assessors[randomAssessor] = 3;
        currentAssessor = randomAssessor;
        potentialAssessorSet = true;
        User(randomAssessor).notification("Called As A Potential Assessor",tag, 1);
      }
    }
    referenceTime = now;
  }

  function getAssessorPoolLength() returns(uint)
  {
      return assessorPool.length;
  }

  function getRandom(uint i) returns(uint)
  {
    return 12;
  }

  function setTask(string data, uint timeLimit)
  {
    if(numberCancelled >= numberOfAssessors)
    {
      cancelAssessment();
    }
    if(assessors[currentAssessor] == 5 && now - referenceTime <= taskCreationTime)
    {
      assessmentTasks[currentAssessor] = data;
      taskCompletionTime = timeLimit;
      assessors[currentAssessor] = 6;
      User(currentAssessor).notification("Task Data Inputted", tag, 5);
      User(assessee).notification("New Task Available", tag, 7);
      referenceTime = now;
    }
    if(now - referenceTime > taskCreationTime && assessors[currentAssessor]!=5)
    {
      User(currentAssessor).notification("Did Not Submit Task On Time", tag, 6);
      Master(master).mapTokenBalance(currentAssessor, Master(master).getTokenBalance(currentAssessor) - 1);
      User(currentAssessor).setReputation(User(currentAssessor).getReputation() + 1);
      numberCancelled++;
      setPotentialAssessor();
    }
  }

  function cancelAssessment()
  {
    User(assessee).notification("Assessment Cancled", tag, 8);
    for(uint i = 0; i < finalAssessors.length; i++)
    {
      User(finalAssessors[i]).notification("Assessment Cancled", tag, 8);
    }
    suicide(master);
  }

  function getTask(address assessorAddress) returns(string)
  {
    return assessmentTasks[assessorAddress];
  }

  function setResponse(string data)
  {
    if(assessors[currentAssessor] == 6 && now - referenceTime <= taskCompletionTime)
    {
      assessmentResponses[currentAssessor] = data;
      assessors[currentAssessor] = 7;
      User(currentAssessor).notification("Task Response Inputted", tag, 10);
      taskGradingTime = (3*(now - referenceTime))/2;
      referenceTime = now;
    }
    if(now - referenceTime > taskCompletionTime && assessors[currentAssessor]!=6)
    {
      User(assessee).notification("Did Not Submit Task Response On Time", tag, 11);
      Master(master).mapTokenBalance(currentAssessor, Master(master).getTokenBalance(assessee) - 1);
      cancelAssessment();
    }
  }

  function getResponse(address assesseeAddress) returns(string)
  {
    return assessmentResponses[assesseeAddress];
  }

  function setResult(int score)
  {
    if(numberCancelled >= numberOfAssessors)
    {
      cancelAssessment();
    }
    if(assessors[currentAssessor] == 7 && now - referenceTime <= taskGradingTime)
    {
      assessmentResults[currentAssessor] = score;
      addressFromScore[score] = currentAssessor;
      User(assessee).notification("Task Result Inputted", tag, 12);
      finalAssessors.push(currentAssessor);
    }
    if(now - referenceTime <= taskGradingTime && assessors[currentAssessor] != 7)
    {
      User(currentAssessor).notification("Did Not Submit Task Results On Time", tag, 13);
      User(assessee).notification("Assessor Has Not Graded In Time", tag, 14);
      Master(master).mapTokenBalance(currentAssessor, Master(master).getTokenBalance(assessee) - 1);
      User(currentAssessor).setReputation(User(currentAssessor).getReputation() + 1);
      numberCancelled++;
      setPotentialAssessor();
    }
    if(finalAssessors.length == numberOfAssessors)
    {
      calculateResult();
    }
    if(finalAssessors.length < numberOfAssessors)
    {
      setPotentialAssessor;
    }
  }

  function calculateMAD(int[] scores, int n) returns(int)
  {
    int meanScore;
    int totalRelativeDistance;
    int meanAbsoluteDeviation;
    for(uint j = 0; j < scores.length; j++)
    {
      meanScore += scores[j];
      inRewardCluster[scores[j]] = false;
    }
    meanScore /= n;
    for(uint k = 0; k < scores.length; k++)
    {
      int distanceFromMean = scores[k] - meanScore;
      if(distanceFromMean < 0)
      {
        distanceFromMean *= -1;
      }
      totalRelativeDistance += distanceFromMean;
    }
    meanAbsoluteDeviation = totalRelativeDistance/n;
  }

  function calculateResult()
  {
    int[][] memory clusters;
    int[] memory scores;
    uint n = 0;
    uint largestClusterIndex = 0;
    int averageScore;
    for(uint i = 0; i < numberOfAssessors; i++)
    {
      scores[i] = assessmentResults[finalAssessors[i]];
    }
    int meanAbsoluteDeviation = calculateMAD(scores,int(numberOfAssessors));
    for(uint l = 0; l < scores.length; l++)
    {
      for(uint m = 0; m < scores.length; m++)
      {
        n = 0;
        if(scores[l] - scores[m] <= meanAbsoluteDeviation)
        {
          clusters[l][n] = (scores[m]);
          n++;
        }
      }
      if(clusters[l].length > clusters[largestClusterIndex].length)
      {
        largestClusterIndex = l;
      }
    }
    for(uint o = 0; o < clusters[largestClusterIndex].length; n++)
    {
      averageScore += clusters[largestClusterIndex][o];
      inRewardCluster[clusters[largestClusterIndex][o]] = true;
    }
    averageScore /= int(clusters[largestClusterIndex].length);
    finalScore = averageScore;
    if(averageScore > 0)
    {
      finalResult = true;
    }
    if(averageScore <= 0)
    {
      finalResult = false;
    }
    payout();
  }

  function confirmAssessor(uint confirm, bool timeKnow)
  {
    if(numberCancelled >= numberOfAssessors)
    {
      cancelAssessment();
    }
    if(assessors[currentAssessor] != 0 && now - referenceTime <= 180)
    {
      assessors[currentAssessor] = confirm;
      if(confirm == 1)
      {
        User(currentAssessor).notification("Confirmed As Potential Assessor", tag, 2);
        referenceTime = now;
      }
      if(confirm == 2 || confirm == 4)
      {
        User(currentAssessor).notification("Confirmed As Not Assessing", tag, 3);
        numberCancelled ++;
        setPotentialAssessor();
      }
      if(confirm == 5)
      {
        User(currentAssessor).notification("Confirmed As Assessing", tag, 9);
        referenceTime = now;
      }
    }
    if(now - referenceTime > 180)
    {
      if(timeKnow == false && assessors[currentAssessor]==3)
      {
      User(currentAssessor).notification("Did Not Respond In Time To Be Assessor", tag, 4);
      Master(master).mapTokenBalance(currentAssessor, Master(master).getTokenBalance(currentAssessor) - 1);
      setPotentialAssessor();
      }
      if(timeKnow == true && assessors[currentAssessor]==1)
      {
        User(currentAssessor).notification("Did Not Respond In Time To Be Assessor", tag, 4);
        setPotentialAssessor();
      }
    }
  }

  function returnResults()
  {
    Tag(tag).finishAssessment(finalResult, finalScore, assessee, address(this));
  }

  function payout()
  {
    for(uint i = 0; i < finalAssessors.length; i++)
    {
      int score = assessmentResults[finalAssessors[i]];
      int scoreDistance = ((score - finalScore)*100)/finalScore;
      if(scoreDistance < 0)
      {
        scoreDistance *= -1;
      }
      uint distance = uint(scoreDistance);
      if(inRewardCluster[score] == true)
      {
        Master(master).mapTokenBalance(finalAssessors[i], Master(master).getTokenBalance(finalAssessors[i]) + uint((500/(100 - scoreDistance))));
        User(finalAssessors[i]).notification("You Have Received Payment For Your Assessment", tag, 15);
      }
      if(inRewardCluster[score] == true)
      {
        Master(master).mapTokenBalance(finalAssessors[i], Master(master).getTokenBalance(finalAssessors[i]) - uint((500/(100 - scoreDistance))));
        User(finalAssessors[i]).notification("You Have Received A Fine For Your Assessment", tag, 16);
      }
    }
  }
}

contract User
{
  address user;
  address master;
  address[] acheivements;
  string userData;
  uint reputation;

  event Notification
  ( string _description,
    address _sender,
    address _user,
    address _tag,
    uint _code);

  function User(address userAddress, address masterAddress)
  {
    user = userAddress;
    master = masterAddress;
    reputation = 1;
  }

  function getReputation() returns(uint)
  {
    return reputation;
  }

  function setReputation(uint newReputation)
  {
    reputation = newReputation;
  }

  function notification(string description, address tag, uint code)
  {
    Notification(description, msg.sender, address(this), tag, code);
  }

  function setUserData(string hash)
  {
    userData = hash;
  }

  function getUserData() returns(string)
  {
    return userData;
  }

  function remove()
  {
    suicide(master);
  }
}


Set up protocols to get and set the assessor pool and select assessors from there for an assessment.

contract Master
{
  //Initialize master data store
  mapping (address => uint) tokenBalance;
  mapping (address => string) tagName;
  mapping (string => address) tagAddressFromName;
  mapping (address => address[]) acheivements;

  function Master()
  {

  }

  function mapTokenBalance(address a, uint b)
  {
    tokenBalance[a] = b;
  }
  function mapTagName(address a, string n)
  {
    tagName[a] = n;
  }
  function mapTagAddressFromName(string n, address a)
  {
    tagAddressFromName[n] = a;
  }
  function mapAcheivement(address a, address t)
  {
    acheivements[a].push(t);
  }
  function getTokenBalance(address a) returns(uint)
  {
    return tokenBalance[a];
  }
  function getTagName(address a) returns(string)
  {
    return tagName[a];
  }
  function getTagAddressFromName(string n) returns(address)
  {
    return tagAddressFromName[n];
  }
  function getAcheivement(address a) returns(address[])
  {
    return acheivements[a];
  }
  function getNumberOfAcheivements(address a) returns(uint)
  {
    return acheivements[a].length;
  }

  function addTag(string name, address[] parentList) returns(uint) //Creates a new tag contract
  {
    uint response = 0;
    if(tokenBalance[msg.sender] < 1)
    {
      response += 1;
    }
    if(tagAddressFromName[name] == 0)
    {
      response += 10;
    }
    if(response==0)
    {
      Tag newTag = new Tag();
      address newTagAddress = address(newTag);
      tagName[newTagAddress] = name;
      tagAddressFromName[name] = newTagAddress;

      for(uint i=0; i<= parentList.length; i++) //adds all the given parents
      {
        if(parentList[i]==0)
        {
          response += 100;
        }
        if(response==0)
        {
          newTag.addParent(parentList[i]);
        }
      }
    }
    newTag.setMaster(address(this));
    newTag.setName(name);
    return response;
  }
}

//Defines the meta-contract for a Tag
contract Tag
{
  address[] parentTags;
  address master;
  string name;
  address[] owners; //Those who have earned the tag
  mapping(address => address[]) assessmentHistory; //All assessments completed
  mapping(address => uint) scores; //All positive assessements scores

  function Tag()
  {

  }

  function addParent(address parentTag)
  {
    parentTags.push(parentTag);
  }

  function setMaster(address m)
  {
    master = m;
  }

  function setName(string n)
  {
    name = n;
  }

  function setAssessorPool(uint s, address a, address assessment)
  {
    for(uint i = 0; i < Tag(a).owners.length && assessment.poolSizeRemaining != 0; i++)
    {
      if(pool.length < .1*Tag(a).owners.length)
      {
        Assessment(assessment).addToAssessorPool(Tag(a).owners[getRandom(Tag(a).owners.length)]);
        s--;
      }
      else
      {
        for(uint j = 0; j < Tag(a).parentTags.length; j++)
        {
          setAssessorPool(s, Tag(a).parentTags[j], assessment);
        }
      }
      if(s == 0)
      {
        Assessment(assessment).setAssessors();
      }
    }
    Assessment(assessment).poolSizeRemaining = s;
  }

  function startAssessment(address assessee, uint size)
  {
    Assessment newAssessment;
    newAssessment.setAssessee(assessee);
    newAssessment.setTag(address(this));
    newAssessment.setNumberOfAssessors(size);
    setAssessorPool(size*20, address(this), address(newAssessment));
  }

  function finishAssessment(bool result, uint score, address assessee, address assessment) returns(bool)
  {
    if(result == true)
    {
      owners.push(assessee);
      scores[assessee] = score;
      Master(master).mapAcheivement(assessee,address(this));
    }
    assessmentHistory[assessee].push(assessment);
    return result;
  }
}

//Defines the meta-contract for an assessment
contract Assessment
{
  address assessee; //We need a better word for this
  address[] assessorPool;
  address[] assessors;
  address tag;
  uint poolSizeRemaining;
  uint numberOfAssessors;
  struct Results
  {
    bool pass;
    uint score;
  }
  mapping(address => uint[]) assessmentQuestions; //Given by the assessors as IPFS hashes
  mapping(address => uint[]) assessmentAnswers; //Given by the assessee as IPFS hashes
  mapping(address => Results) assessmentResults; //Pass/Fail and Score given by assessors
  uint finalScore;
  bool finalResult;

  function Assessment()
  {

  }

  function setAssessee(address newAssessee)
  {
    assessee = newAssessee;
  }

  function setNumberOfAssessors(uint n)
  {
    numberOfAssessors = n;
  }

  function addToAssessorPool(address a)
  {
    assessorPool.push(a);
  }

  function setAssessors()
  {
    for(uint i = 0, i < n, i++)
    {
      assessors.push(assessorPool[getRandom(assessorPool.length)]);
    }
  }

  function setTag(address t)
  {
    tag = t;
  }

  function setQuestion(address a, uint[] data)
  {
    assessmentQuestions[a] = data;
  }

  function getQuestion(address a) returns(uint[])
  {
    return assessmentQuestions[a];
  }

  function setAnswer(address a, uint[] data)
  {
    assessmentAnswers[a] = data;
  }

  function getAnswer(address a) returns(uint[])
  {
    return assessmentAnswers[a];
  }

  function setResult(address a, bool b, uint s)
  {
    Results memory results;
    results.pass = b;
    results.score = s;
    assessmentResults[a] = results;
  }

  function assess()
  {

  }

  function calculateResult()
  {

  }

  function returnResults()
  {
    Tag(tag).finishAssessment(finalResult, finalScore, assessee, address(this));
  }

  function cashout()
  {

  }
}

contract Master
{
  //Initialize master data store
  mapping (address => uint) tokenBalance;
  mapping (address => string) tagName;
  mapping (string => address) tagAddressFromName;
  mapping (address => address[]) acheivements;

  function Master()
  {

  }

  function mapTokenBalance(address a, uint b)
  {
    tokenBalance[a] = b;
  }
  function mapTagName(address a, string n)
  {
    tagName[a] = n;
  }
  function mapTagAddressFromName(string n, address a)
  {
    tagAddressFromName[n] = a;
  }
  function mapAcheivement(address a, address t)
  {
    acheivements[a].push(t);
  }
  function getTokenBalance(address a) returns(uint)
  {
    return tokenBalance[a];
  }
  function getTagName(address a) returns(string)
  {
    return tagName[a];
  }
  function getTagAddressFromName(string n) returns(address)
  {
    return tagAddressFromName[n];
  }
  function getAcheivement(address a) returns(address[])
  {
    return acheivements[a];
  }
  function getNumberOfAcheivements(address a) returns(uint)
  {
    return acheivements[a].length;
  }

  function addTag(string name, address[] parentList) returns(uint) //Creates a new tag contract
  {
    uint response = 0;
    if(tokenBalance[msg.sender] < 1)
    {
      response += 1;
    }
    if(tagAddressFromName[name] == 0)
    {
      response += 10;
    }
    if(response==0)
    {
      Tag newTag = new Tag();
      address newTagAddress = address(newTag);
      tagName[newTagAddress] = name;
      tagAddressFromName[name] = newTagAddress;

      for(uint i=0; i<= parentList.length; i++) //adds all the given parents
      {
        if(parentList[i]==0)
        {
          response += 100;
        }
        if(response==0)
        {
          newTag.addParent(parentList[i]);
        }
      }
    }
    newTag.setMaster(address(this));
    newTag.setName(name);
    return response;
  }
}

//Defines the meta-contract for a Tag
contract Tag
{
  address[] parentTags;
  address master;
  string name;
  address[] owners; //Those who have earned the tag
  mapping(address => address[]) assessmentHistory; //All assessments completed
  mapping(address => uint) scores; //All positive assessements scores

  function Tag()
  {

  }

  function addParent(address parentTag)
  {
    parentTags.push(parentTag);
  }

  function setMaster(address m)
  {
    master = m;
  }

  function setName(string n)
  {
    name = n;
  }

  function getAssessors(uint randomNumber) returns(address[])
  {

  }

  function startAssessment(address assessee, address[] assessors)
  {
    Assessment newAssessment;
    newAssessment.setAssessee(assessee);
    newAssessment.setAssessors(assessors);
    newAssessment.setTag(address(this));
  }

  function finishAssessment(bool result, uint score, address assessee, address assessment) returns(bool)
  {
    if(result == true)
    {
      owners.push(assessee);
      scores[assessee] = score;
      Master(master).mapAcheivement(assessee,address(this));
    }
    assessmentHistory[assessee].push(assessment);
    return result;
  }
}

//Defines the meta-contract for an assessment
contract Assessment
{
  address assessee; //We need a better word for this
  address[] assessors;
  address tag;
  struct Results
  {
    bool pass;
    uint score;
  }
  mapping(address => uint[]) assessmentQuestions; //Given by the assessors as IPFS hashes
  mapping(address => uint[]) assessmentAnswers; //Given by the assessee as IPFS hashes
  mapping(address => Results) assessmentResults; //Pass/Fail and Score given by assessors
  uint finalScore;
  bool finalResult;

  function Assessment()
  {

  }

  function setAssessee(address newAssessee)
  {
    assessee = newAssessee;
  }

  function setAssessors(address[] newAssessors)
  {
    assessors = newAssessors;
  }

  function setTag(address t)
  {
    tag = t;
  }

  function setQuestion(address a, uint[] data)
  {
    assessmentQuestions[a] = data;
  }

  function getQuestion(address a) returns(uint[])
  {
    return assessmentQuestions[a];
  }

  function setAnswer(address a, uint[] data)
  {
    assessmentAnswers[a] = data;
  }

  function getAnswer(address a) returns(uint[])
  {
    return assessmentAnswers[a];
  }

  function setResult(address a, bool b, uint s)
  {
    Results memory results;
    results.pass = b;
    results.score = s;
    assessmentResults[a] = results;
  }

  function assess()
  {

  }

  function calculateResult()
  {

  }

  function returnResults()
  {
    Tag(tag).finishAssessment(finalResult, finalScore, assessee, address(this));
  }

  function cashout()
  {

  }
}


remove onlyMember modifier

remove onlyMember modifier

import ../user.sol

contract Group
{
  uint public size;
  bytes32 public goal;
  address[] public members;
  address[] public requirements;
  address concept;
  address registry;
  mapping (address => bool) done;

  modifier onlyRegistry()
  {
    if (msg.sender != registry)
    {
      throw;
    }
    _;
  }

  function Group(address _concept, uint _size, address[] _requirements)
  {
    concept = _concept;
    registry = msg.sender;
    requirements = _requirements;
    members.push(member);
    size = _size;
  }

  function addMember(address member) onlyRegistry()
  {
    if(members.length() < size)
    {
      members.push(member);
    }
  }

  function setDone()
  {
    done(msg.sender) = true;
    for(uint i = 0, if i <= members.length(), i++)
    {
      if(done[members[i]] == false)
      {
        return;
      }
    }
    //Call some thing to do if the whole group is done here
  }

}

import ../user.sol

contract Group
{
  uint public size;
  bytes32 public goal;
  address[] public members;
  address[] public requirements;
  address concept;
  address registry;
  mapping (address => bool) done;

  modifier onlyRegistry()
  {
    if (msg.sender != registry)
    {
      throw;
    }
    _;
  }
  modifier onlyMember()
  {
    if (msg.sender )
  }

  function Group(address _concept, uint _size, address[] _requirements)
  {
    concept = _concept;
    registry = msg.sender;
    requirements = _requirements;
    members.push(member);
    size = _size;
  }

  function addMember(address member) onlyRegistry()
  {
    if(members.length() < size)
    {
      members.push(member);
    }
  }

  function setDone()
  {
    done(msg.sender) = true;
    for(uint i = 0, if i <= members.length(), i++)
    {
      if(done[members[i]] == false)
      {
        return
      }
    }
    //Call some thing to do if the whole group is done here
  }

}


rename setAvailability to toggleAvailability

pragma solidity ^0.4.11;

import "./FathomToken.sol";
import "./ConceptRegistry.sol";
import "./Assessment.sol";
import "./Math.sol";

//@purpose: To store concept data and create and manage assessments and members
contract Concept {
    address[] public parents; //The concepts that this concept is child to (ie: Calculus is child to Math)
    bytes public data;

    FathomToken public fathomToken;
    ConceptRegistry conceptRegistry;
    uint public lifetime;
    mapping (address => bool) public assessmentExists;

    uint[] propagationRates;

    address[] public members;
    mapping (address => MemberData) public memberData;

    struct MemberData {
        address recentAssessment;
        uint index;
        ComponentWeight[] weights;
        mapping(address => uint) componentWeightIndex;
    }

    struct ComponentWeight {
        uint weight;
        uint date;
    }

    modifier onlyConcept() {
        require(conceptRegistry.conceptExists(msg.sender));
        _;
    }

    function Concept(address[] _parents, uint[] _propagationRates, uint _lifetime, bytes _data) public {
        require(_parents.length == _propagationRates.length);
        conceptRegistry = ConceptRegistry(msg.sender);

        for (uint j=0; j < _parents.length; j++) {
            require(conceptRegistry.conceptExists(_parents[j]));
            require(_propagationRates[j] <= 1000);
        }

        propagationRates = _propagationRates;
        parents = _parents;
        data = _data;
        lifetime = _lifetime;
        fathomToken = FathomToken(conceptRegistry.fathomToken());
    }

    function getMemberLength() public view returns(uint) {
        return members.length;
    }

    function getParentsLength() public view returns(uint) {
        return parents.length;
    }

    /*
      @purpose: To add the firstUser to Mew
    */
    function addInitialMember(address _user, uint _weight) public {
        if (conceptRegistry.distributorAddress() == msg.sender)
            {
                this.addWeight(_user, _weight);
            }
    }

    /*
      @purpose: add the caller of this function to the arrays of potential assessors
      if they still have a weight in the concept
      @returns true if they are available as assessor
    */
    function toggleAvailability() public returns(bool success){
        if (getWeightAndUpdate(msg.sender) > 0) {
            if (memberData[msg.sender].index == 0) {
                members.push(msg.sender);
                memberData[msg.sender].index = members.length;
                success = true;
            }
            else {
                removeMember(msg.sender);
            }
        }
   }

    /*
      //@purpose: returns a random member of the Concept or the zero address (both with approx. 50%)
      //Users with high weights are more likely to be called
      //@returns the address of the member (0x0 if there is no member)
    */
    function getWeightedRandomMember(uint seed) public returns(address){
        uint weight1;
        uint weight2;
        address randomMember1;
        while (members.length > 1 && weight1 == 0) {
            uint index1 = Math.getRandom(seed, members.length - 1);
            randomMember1 = members[index1];
            weight1 = getWeightAndUpdate(randomMember1);
            seed++;
        }
        while (members.length > 1 && weight2 == 0) {
                uint index2 = Math.getRandom(seed * 2, members.length - 1);
                address randomMember2 = members[index2];
                weight2 = getWeightAndUpdate(randomMember2);
                seed += 10;
        }
        if (weight1 > weight2) {
            return randomMember1;
        }
    }

    /*
      @purpose: get the weight of a given member, also removes that member from the array
      if there legitimating assessment is expired
    */
    function getWeight(address _member) view public returns(uint weight){
        for (uint i=0; i < memberData[_member].weights.length; i++) {
            if (memberData[_member].weights[i].date > now){
                weight += memberData[_member].weights[i].weight;
            }
        }
    }

    //@purpose: check weight and update members array
    function getWeightAndUpdate(address _member) public returns(uint weight) {
        weight = getWeight(_member);
        if (weight == 0) {
            removeMember(_member);
        }
    }

    /*
      @purpose: removes member at a given index from the members array by substituting they with
      the last member and then decreasing the size of the members array
      @returns the updated number of members in the concept
    */
    function removeMember(address _member) private returns(uint){
        uint index = memberData[_member].index;
        if (index > 0){
            members[index] = members[members.length - 1]; //THIS NEEDS TO BE TESTED!
            memberData[_member].index = 0;
            members.length--;
        }
        return members.length;
    }

    /*
      @purpose: To make a new assessment
      NOTE: While there are less than 200 members in network, all members of mew will
      be called as assessors for any concept
      @param: uint cost = the cost per assessor
      @param: uint size = the number of assessors
    */
    function makeAssessment(uint cost, uint size, uint _waitTime, uint _timeLimit) public returns(bool) {
        if (size >= 5 && fathomToken.balanceOf(msg.sender)>= cost*size) {
            Assessment newAssessment = new Assessment(msg.sender, size, cost, _waitTime, _timeLimit);
            assessmentExists[address(newAssessment)] = true;
            fathomToken.takeBalance(msg.sender, address(newAssessment), cost*size, address(this));
            // get membernumber of mew to see whether there are more than 200 users in the system:
            address mewAddress = conceptRegistry.mewAddress();
            uint nMemberInMew = Concept(mewAddress).getMemberLength();
            if (nMemberInMew < size * 5) {
                newAssessment.callAllFromMew(nMemberInMew, mewAddress);
            } else {
                newAssessment.setAssessorPool(block.number, address(this), size*5);
            }
            return true;
        }
    }

    /*
      @purpose: To add a member to a concept and to recursively add  a member to parent concept
      @param: address assessee = the address of the assessee
      @param: uint weight = the weight for the member
      @returns: nothing
    */
    function addMember(address _assessee, uint _weight) public {
        if (assessmentExists[msg.sender]) {
            memberData[_assessee].recentAssessment = msg.sender;
            this.addWeight(_assessee, _weight);
        }
    }

    function addWeight(address _assessee, uint _weight) public onlyConcept() {
        if (memberData[_assessee].index == 0) {
            members.push(_assessee);
            memberData[_assessee].index = members.length;
        }

        uint idx = memberData[_assessee].componentWeightIndex[msg.sender];
        if (idx > 0) {
            memberData[_assessee].weights[idx-1] = ComponentWeight(_weight, now + lifetime);
        } else {
            memberData[_assessee].weights.push(ComponentWeight(_weight, now + lifetime));
            memberData[_assessee].componentWeightIndex[msg.sender] = memberData[_assessee].weights.length;
        }

        for(uint i = 0; i < parents.length; i++) {
            if((_weight*propagationRates[i])/1000 > 0) {
                Concept(parents[i]).addWeight(_assessee, (_weight*propagationRates[i])/1000);
            }
        }
    }
}

pragma solidity ^0.4.11;

import "./FathomToken.sol";
import "./ConceptRegistry.sol";
import "./Assessment.sol";
import "./Math.sol";

//@purpose: To store concept data and create and manage assessments and members
contract Concept {
    address[] public parents; //The concepts that this concept is child to (ie: Calculus is child to Math)
    bytes public data;

    FathomToken public fathomToken;
    ConceptRegistry conceptRegistry;
    uint public lifetime;
    mapping (address => bool) public assessmentExists;

    uint[] propagationRates;

    address[] public members;
    mapping (address => MemberData) public memberData;

    struct MemberData {
        address recentAssessment;
        uint index;
        ComponentWeight[] weights;
        mapping(address => uint) componentWeightIndex;
    }

    struct ComponentWeight {
        uint weight;
        uint date;
    }

    modifier onlyConcept() {
        require(conceptRegistry.conceptExists(msg.sender));
        _;
    }

    function Concept(address[] _parents, uint[] _propagationRates, uint _lifetime, bytes _data) public {
        require(_parents.length == _propagationRates.length);
        conceptRegistry = ConceptRegistry(msg.sender);

        for (uint j=0; j < _parents.length; j++) {
            require(conceptRegistry.conceptExists(_parents[j]));
            require(_propagationRates[j] <= 1000);
        }

        propagationRates = _propagationRates;
        parents = _parents;
        data = _data;
        lifetime = _lifetime;
        fathomToken = FathomToken(conceptRegistry.fathomToken());
    }

    function getMemberLength() public view returns(uint) {
        return members.length;
    }

    function getParentsLength() public view returns(uint) {
        return parents.length;
    }

    /*
      @purpose: To add the firstUser to Mew
    */
    function addInitialMember(address _user, uint _weight) public {
        if (conceptRegistry.distributorAddress() == msg.sender)
            {
                this.addWeight(_user, _weight);
            }
    }

    /*
      @purpose: add the caller of this function to the arrays of potential assessors
      if they still have a weight in the concept
      @returns true if they are available as assessor
    */
    function setAvailability() public returns(bool success){
        if (getWeightAndUpdate(msg.sender) > 0) {
            if (memberData[msg.sender].index == 0) {
                members.push(msg.sender);
                memberData[msg.sender].index = members.length;
                success = true;
            }
            else {
                removeMember(msg.sender);
            }
        }
   }

    /*
      //@purpose: returns a random member of the Concept or the zero address (both with approx. 50%)
      //Users with high weights are more likely to be called
      //@returns the address of the member (0x0 if there is no member)
    */
    function getWeightedRandomMember(uint seed) public returns(address){
        uint weight1;
        uint weight2;
        address randomMember1;
        while (members.length > 1 && weight1 == 0) {
            uint index1 = Math.getRandom(seed, members.length - 1);
            randomMember1 = members[index1];
            weight1 = getWeightAndUpdate(randomMember1);
            seed++;
        }
        while (members.length > 1 && weight2 == 0) {
                uint index2 = Math.getRandom(seed * 2, members.length - 1);
                address randomMember2 = members[index2];
                weight2 = getWeightAndUpdate(randomMember2);
                seed += 10;
        }
        if (weight1 > weight2) {
            return randomMember1;
        }
    }

    /*
      @purpose: get the weight of a given member, also removes that member from the array
      if there legitimating assessment is expired
    */
    function getWeight(address _member) view public returns(uint weight){
        for (uint i=0; i < memberData[_member].weights.length; i++) {
            if (memberData[_member].weights[i].date > now){
                weight += memberData[_member].weights[i].weight;
            }
        }
    }

    //@purpose: check weight and update members array
    function getWeightAndUpdate(address _member) public returns(uint weight) {
        weight = getWeight(_member);
        if (weight == 0) {
            removeMember(_member);
        }
    }

    /*
      @purpose: removes member at a given index from the members array by substituting they with
      the last member and then decreasing the size of the members array
      @returns the updated number of members in the concept
    */
    function removeMember(address _member) private returns(uint){
        uint index = memberData[_member].index;
        if (index > 0){
            members[index] = members[members.length - 1]; //THIS NEEDS TO BE TESTED!
            memberData[_member].index = 0;
            members.length--;
        }
        return members.length;
    }

    /*
      @purpose: To make a new assessment
      NOTE: While there are less than 200 members in network, all members of mew will
      be called as assessors for any concept
      @param: uint cost = the cost per assessor
      @param: uint size = the number of assessors
    */
    function makeAssessment(uint cost, uint size, uint _waitTime, uint _timeLimit) public returns(bool) {
        if (size >= 5 && fathomToken.balanceOf(msg.sender)>= cost*size) {
            Assessment newAssessment = new Assessment(msg.sender, size, cost, _waitTime, _timeLimit);
            assessmentExists[address(newAssessment)] = true;
            fathomToken.takeBalance(msg.sender, address(newAssessment), cost*size, address(this));
            // get membernumber of mew to see whether there are more than 200 users in the system:
            address mewAddress = conceptRegistry.mewAddress();
            uint nMemberInMew = Concept(mewAddress).getMemberLength();
            if (nMemberInMew < size * 5) {
                newAssessment.callAllFromMew(nMemberInMew, mewAddress);
            } else {
                newAssessment.setAssessorPool(block.number, address(this), size*5);
            }
            return true;
        }
    }

    /*
      @purpose: To add a member to a concept and to recursively add  a member to parent concept
      @param: address assessee = the address of the assessee
      @param: uint weight = the weight for the member
      @returns: nothing
    */
    function addMember(address _assessee, uint _weight) public {
        if (assessmentExists[msg.sender]) {
            memberData[_assessee].recentAssessment = msg.sender;
            this.addWeight(_assessee, _weight);
        }
    }

    function addWeight(address _assessee, uint _weight) public onlyConcept() {
        if (memberData[_assessee].index == 0) {
            members.push(_assessee);
            memberData[_assessee].index = members.length;
        }

        uint idx = memberData[_assessee].componentWeightIndex[msg.sender];
        if (idx > 0) {
            memberData[_assessee].weights[idx-1] = ComponentWeight(_weight, now + lifetime);
        } else {
            memberData[_assessee].weights.push(ComponentWeight(_weight, now + lifetime));
            memberData[_assessee].componentWeightIndex[msg.sender] = memberData[_assessee].weights.length;
        }

        for(uint i = 0; i < parents.length; i++) {
            if((_weight*propagationRates[i])/1000 > 0) {
                Concept(parents[i]).addWeight(_assessee, (_weight*propagationRates[i])/1000);
            }
        }
    }
}


Pass parser and tokens as parameters to functions

pragma solidity ^0.4.2;

contract JsmnSol {

    event Info(string msg);
    event TokenInfo(JsmnType jsmnType, int start, int end, uint8 size);
    event Debug(int toksuper, int length);

    enum JsmnType { UNDEFINED, OBJECT, ARRAY, STRING, PRIMITIVE }
    enum JsmnError { INVALID, ERROR_PART }

    struct JsmnToken {
        JsmnType jsmnType;
        int start;
        int end;
        uint8 size;
    }

    struct Parser {
        uint pos;
        uint toknext;
        int toksuper;
    }

    JsmnToken[] storageTokens;

    function jsmnInit(uint length) internal returns (Parser, JsmnToken[]) {
        Parser memory p = Parser(0, 0, -1);
        JsmnToken[] memory t = new JsmnToken[](length);
        return (p, t);
    }

    function allocateToken(Parser parser, JsmnToken[] tokens) internal returns (bool, JsmnToken) {
        Info('allocateToken');
        if (parser.toknext >= tokens.length) {
            // no more space in tokens
            return (false, tokens[tokens.length-1]);
        }
        tokens[parser.toknext] = JsmnToken(JsmnType.UNDEFINED, -1, -1, 0);
        parser.toknext++;
        return (true, tokens[parser.toknext-1]);
    }

    function fillToken(JsmnToken token, JsmnType jsmnType, int start, int end) internal {
        token.jsmnType = jsmnType;
        token.start = start;
        token.end = end;
        token.size = 0;
    }

    function parseString(Parser parser, JsmnToken[] tokens, bytes s) internal returns (int) {
        uint start = parser.pos;
        uint ti;
        parser.pos++;

        for (; parser.pos<s.length; parser.pos++) {
            bytes1 c = s[parser.pos];

            // Quote -> end of string
            if (c == '"') {
                var (result, token) = allocateToken(parser, tokens);
                fillToken(token, JsmnType.STRING, int(start+1), int(parser.pos-1));
                return 0;
            }

            if (c == '\\') {
                // TODO handle escaped characters
            }
        }
        parser.pos = start;
        return int(JsmnError.ERROR_PART);
    }

    function parsePrimitive(Parser parser, JsmnToken[] tokens, bytes s) internal returns (int) {
        bool found = false;
        uint start = parser.pos;
        byte c;
        uint ti;
        for (; parser.pos < s.length; parser.pos++) {
            c = s[parser.pos];
            if (c == ' ' || c == '\t' || c == '\n' || c == '\r' //|| c == ','
                || c == 0x7d || c == 0x5d) {
                    found = true;
                    break;
            }
            if (c < 32 || c > 127) {
                parser.pos = start;
                return int(JsmnError.INVALID);
            }
        }
        if (!found) {
            parser.pos = start;
            return int(JsmnError.ERROR_PART);
        }

        // found the end
        var (result, token) = allocateToken(parser, tokens);
        fillToken(token, JsmnType.PRIMITIVE, int(start), int(parser.pos));
        parser.pos--;
        return 0;
    }

    function jsmnParse(string json, uint numberElements) returns (JsmnError) {
        bytes memory s = bytes(json);
        var (parser, tokens) = jsmnInit(numberElements);

        // JsmnToken memory token;
        int r;
        uint ti;
        uint count = parser.toknext;
        uint i;

        for (; parser.pos<s.length; parser.pos++) {
            bytes1 c = s[parser.pos];

            // 0x7b, 0x5b opening parentheses
            if (c == 0x7b || c == 0x5b) {
                Info('Opening parentheses');
                count++;
                //token = allocateToken();
                var (result, token)= allocateToken(parser, tokens);
                if (parser.toksuper != -1) {
                    tokens[uint(parser.toksuper)].size++;
                }
                token.jsmnType = (c == 0x7b ? JsmnType.OBJECT : JsmnType.ARRAY);
                token.start = int(parser.pos);
                parser.toksuper = int(parser.toknext - 1);
                continue;
            }

            // closing parentheses
            if (c == 0x7d || c == 0x5d) {
                Info('Closing parentheses');
                JsmnType tokenType = (c == 0x7d ? JsmnType.OBJECT : JsmnType.ARRAY);
                bool isUpdated = false;
                for (i=parser.toknext; i>=0; i--) {
                    //token = tokens[uint(i)];
                    if (tokens[i].start != -1 && tokens[i].end == -1) {
                        if (tokens[i].jsmnType != tokenType) {
                            // found a token that hasn't been closed but from a different type
                            Info('Error: wrong type');
                            return JsmnError.INVALID;
                        }
                        parser.toksuper = -1;
                        tokens[i].end = int(parser.pos);
                        isUpdated = true;
                        break;
                    }
                }
                if (!isUpdated) {
                    Info('Error: No update');
                    return JsmnError.INVALID;
                }
                for (; i>0; i--) {
                    //token = tokens[uint(i)];
                    if (tokens[i].start != -1 && tokens[i].end == -1) {
                        parser.toksuper = uint128(i);
                        break;
                    }
                }

                if (i==0) {
                    if (tokens[i].start != -1 && tokens[i].end == -1) {
                        parser.toksuper = uint128(i);
                    }
                }
                continue;
            }

            // 0x42
            if (c == '"') {
                Info('Double quote');
                r = parseString(parser, tokens, s);
                if (r < 0) return JsmnError.INVALID;
                count++;
				if (parser.toksuper != -1)
					tokens[uint(parser.toksuper)].size++;
                continue;
            }

            // ' ', \r, \t, \n
            if (c == ' ' || c == 0x11 || c == 0x12 || c == 0x14) {
                Info('Whitespace');
                continue;
            }

            // 0x3a
            if (c == ':') {
                Info('Colon');
                parser.toksuper = int(parser.toknext -1);
                continue;
            }

            if (c == ',') {
                Info('Comma');
                if (parser.toksuper != -1
                    && tokens[uint(parser.toksuper)].jsmnType != JsmnType.ARRAY
                    && tokens[uint(parser.toksuper)].jsmnType != JsmnType.OBJECT) {
                        for(i = parser.toknext-1; i>=0; i--) {
                            if (tokens[i].jsmnType == JsmnType.ARRAY || tokens[i].jsmnType == JsmnType.OBJECT) {
                                if (tokens[i].start != -1 && tokens[i].end == -1) {
                                    parser.toksuper = int(i);
                                }
                            }
                        }
                    }
                continue;
            }

            if ((c >= '0' && c <= '9') || c == 'f' || c == 't' || c == 'n') {
                Info('Primitive');
                if (parser.toksuper != -1) {
                    if (tokens[uint(parser.toksuper)].jsmnType == JsmnType.OBJECT
                        || (tokens[uint(parser.toksuper)].jsmnType == JsmnType.STRING
                            && tokens[uint(parser.toksuper)].size != 0)) {
                            return JsmnError.INVALID;
                        }
                }

                parsePrimitive(parser, tokens, s);

                continue;
            }

            if (c >= 0x20 && c <= 0x7e) {
                Info('Printable char');
                continue;
            }
        }

        for (i=0; i<parser.toknext; i++) {
            storageTokens.push(tokens[i]);
        }
    }

    function getAllTokens() {
        for (uint i=0; i<storageTokens.length; i++) {
            JsmnToken t = storageTokens[i];
            TokenInfo(t.jsmnType, t.start, t.end, t.size);
        }
    }

    function bytes32ToString(bytes32 x) constant returns (string) {
        bytes memory bytesString = new bytes(32);
        uint charCount = 0;
        for (uint j = 0; j < 32; j++) {
            byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
            if (char != 0) {
                bytesString[charCount] = char;
                charCount++;
            }
        }
        bytes memory bytesStringTrimmed = new bytes(charCount);
        for (j = 0; j < charCount; j++) {
            bytesStringTrimmed[j] = bytesString[j];
        }
        return string(bytesStringTrimmed);
    }

}

pragma solidity ^0.4.2;

contract JsmnSol {

    event Info(string msg);
    event TokenInfo(JsmnType jsmnType, int start, int end, uint8 size);
    event Debug(int toksuper, int length);

    enum JsmnType { UNDEFINED, OBJECT, ARRAY, STRING, PRIMITIVE }
    enum JsmnError { INVALID, ERROR_PART }

    struct JsmnToken {
        JsmnType jsmnType;
        int start;
        int end;
        uint8 size;
    }

    struct Parser {
        uint pos;
        int toksuper;
    }

    Parser parser;
    JsmnToken[] tokens;

    function jsmnInit() public {
        parser = Parser(0, -1);
        tokens.length = 0;
    }

    function allocateToken() internal returns (uint) {
        Info('allocateToken');
        tokens.length++;
        tokens[tokens.length - 1] = JsmnToken(JsmnType.UNDEFINED, -1, -1, 0);
        return tokens.length - 1;
    }

    function fillToken(uint ti, JsmnType jsmnType, int start, int end) {
        tokens[ti].jsmnType = jsmnType;
        tokens[ti].start = start;
        tokens[ti].end = end;
        tokens[ti].size = 0;
    }

    function parseString(bytes s) returns (int) {
        uint start = parser.pos;
        uint ti;
        parser.pos++;

        for (; parser.pos<s.length; parser.pos++) {
            bytes1 c = s[parser.pos];

            // Quote -> end of string
            if (c == '"') {
                ti = allocateToken();
                fillToken(ti, JsmnType.STRING, int(start+1), int(parser.pos-1));
                return 0;
            }

            if (c == '\\') {
                // TODO handle escaped characters
            }
        }
        parser.pos = start;
        return int(JsmnError.ERROR_PART);
    }

    function parsePrimitive(bytes s) returns (int) {
        bool found = false;
        uint start = parser.pos;
        byte c;
        uint ti;
        for (; parser.pos < s.length; parser.pos++) {
            c = s[parser.pos];
            if (c == ' ' || c == '\t' || c == '\n' || c == '\r' //|| c == ','
                || c == 0x7d || c == 0x5d) {
                    found = true;
                    break;
            }
            if (c < 32 || c > 127) {
                parser.pos = start;
                return int(JsmnError.INVALID);
            }
        }
        if (!found) {
            parser.pos = start;
            return int(JsmnError.ERROR_PART);
        }

        // found the end
        ti = allocateToken();
        fillToken(ti, JsmnType.PRIMITIVE, int(start), int(parser.pos));
        parser.pos--;
        return 0;
    }

    function jsmnParse(string json) returns (JsmnError) {
        bytes memory s = bytes(json);
        jsmnInit();

        // JsmnToken memory token;
        int r;
        uint ti;
        uint count = tokens.length;
        uint128 i;

        for (; parser.pos<s.length; parser.pos++) {
            bytes1 c = s[parser.pos];

            // 0x7b, 0x5b opening parentheses
            if (c == 0x7b || c == 0x5b) {
                Info('Opening parentheses');
                count++;
                //token = allocateToken();
                ti = allocateToken();
                if (parser.toksuper != -1) {
                    tokens[uint(parser.toksuper)].size++;
                }
                tokens[ti].jsmnType = (c == 0x7b ? JsmnType.OBJECT : JsmnType.ARRAY);
                tokens[ti].start = int(parser.pos);
                parser.toksuper = int(tokens.length - 1);
                continue;
            }

            // closing parentheses
            if (c == 0x7d || c == 0x5d) {
                Info('Closing parentheses');
                JsmnType tokenType = (c == 0x7d ? JsmnType.OBJECT : JsmnType.ARRAY);
                bool isUpdated = false;
                for (i=uint128(tokens.length-1); i>=0; i--) {
                    //token = tokens[uint(i)];
                    if (tokens[i].start != -1 && tokens[i].end == -1) {
                        if (tokens[i].jsmnType != tokenType) {
                            // found a token that hasn't been closed but from a different type
                            Info('Error: wrong type');
                            return JsmnError.INVALID;
                        }
                        parser.toksuper = -1;
                        tokens[i].end = int(parser.pos);
                        isUpdated = true;
                        break;
                    }
                }
                if (!isUpdated) {
                    Info('Error: No update');
                    return JsmnError.INVALID;
                }
                for (; i>0; i--) {
                    //token = tokens[uint(i)];
                    if (tokens[i].start != -1 && tokens[i].end == -1) {
                        parser.toksuper = uint128(i);
                        break;
                    }
                }

                if (i==0) {
                    if (tokens[i].start != -1 && tokens[i].end == -1) {
                        parser.toksuper = uint128(i);
                    }
                }
                continue;
            }

            // 0x42
            if (c == '"') {
                Info('Double quote');
                r = parseString(s);
                if (r < 0) return JsmnError.INVALID;
                count++;
				if (parser.toksuper != -1)
					tokens[uint(parser.toksuper)].size++;
                continue;
            }

            // ' ', \r, \t, \n
            if (c == ' ' || c == 0x11 || c == 0x12 || c == 0x14) {
                Info('Whitespace');
                continue;
            }

            // 0x3a
            if (c == ':') {
                Info('Colon');
                parser.toksuper = int(tokens.length -1);
                continue;
            }

            if (c == ',') {
                Info('Comma');
                if (parser.toksuper != -1
                    && tokens[uint(parser.toksuper)].jsmnType != JsmnType.ARRAY
                    && tokens[uint(parser.toksuper)].jsmnType != JsmnType.OBJECT) {
                        for(i = uint128(tokens.length)-1; i>=0; i--) {
                            if (tokens[i].jsmnType == JsmnType.ARRAY || tokens[i].jsmnType == JsmnType.OBJECT) {
                                if (tokens[i].start != -1 && tokens[i].end == -1) {
                                    parser.toksuper = i;
                                }
                            }
                        }
                    }
                continue;
            }

            if ((c >= '0' && c <= '9') || c == 'f' || c == 't' || c == 'n') {
                Info('Primitive');
                if (parser.toksuper != -1) {
                    if (tokens[uint(parser.toksuper)].jsmnType == JsmnType.OBJECT
                        || (tokens[uint(parser.toksuper)].jsmnType == JsmnType.STRING
                            && tokens[uint(parser.toksuper)].size != 0)) {
                            return JsmnError.INVALID;
                        }
                }

                parsePrimitive(s);

                continue;
            }

            if (c >= 0x20 && c <= 0x7e) {
                Info('Printable char');
                continue;
            }
        }
    }

    function getAllTokens() {
        for (uint i=0; i<tokens.length; i++) {
            JsmnToken t = tokens[i];
            TokenInfo(t.jsmnType, t.start, t.end, t.size);
        }
    }

    function bytes32ToString(bytes32 x) constant returns (string) {
        bytes memory bytesString = new bytes(32);
        uint charCount = 0;
        for (uint j = 0; j < 32; j++) {
            byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
            if (char != 0) {
                bytesString[charCount] = char;
                charCount++;
            }
        }
        bytes memory bytesStringTrimmed = new bytes(charCount);
        for (j = 0; j < charCount; j++) {
            bytesStringTrimmed[j] = bytesString[j];
        }
        return string(bytesStringTrimmed);
    }

}