class Member{
	lazy Integer refundPercentage;

	memberStatus{
    	Unbanned{
		ban()-> Banned;
		}
		Banned{}
    }

}


class Guide {
  
  // Returns true if a guide has no assignment for 
  // a given number of weeks
  // @author Asma Gandour
  public boolean isAvailableFor(Integer nbrWeeks){
    if(hasAssignments()){
      Integer lastWeek = getAssignment(numberOfAssignments()-1).getEndWeek();
      if(getClimbSafe().getNrWeeks()-lastWeek < nbrWeeks)
        return false;
    }
    
    return true;
  }
  
	// Assigns this guide to members that require a guide
	// until the guide is not available anymore
	// @author Asma Gandour
	public boolean performAssignmentToMembers(){
		Integer startWeek = 1;
		Integer endWeek;
		for(Member member: climbSafe.getMembers()){

			if(member.getAssignment() == null){
				if(!member.isGuideRequired()){

					endWeek = startWeek + member.getNrWeeks() - 1;
					Assignment assignment = new Assignment(startWeek, endWeek, member, climbSafe);
					climbSafe.addAssignment(assignment);
					member.getAssignment().toggleStatus();

				}else{
					if(isAvailableFor(member.getNrWeeks())){
						if(hasAssignments()){
							startWeek = getAssignment(numberOfAssignments()-1).getEndWeek()+1;

						}
						endWeek = startWeek + member.getNrWeeks() - 1;
						Assignment assignment = new Assignment(startWeek, endWeek, member, climbSafe);
						addAssignment(assignment);
						climbSafe.addAssignment(assignment);
						member.getAssignment().toggleStatus();


					}

				}
			}
		}

		return true;
	}
  
}

  
class Assignment{
    lazy String paymentAuthorizationCode;

    assignmentStatus{
    
	  Unassigned{
	   toggleStatus() -> Assigned;
	  		
	  }Assigned{
        pay()[!member.getMemberStatusFullName().equals("Banned")]-> Paid;
        startTrip()/{getMember().ban();}-> Assigned;
        cancelTrip()[!member.getMemberStatusFullName().equals("Banned")] -> Cancelled;  
      }
      
      Paid{
        startTrip() -> Started;
        cancelTrip() -> Cancelled;  
      }
      
      Started {
        
        finishTrip() -> Finished;
        cancelTrip() -> Cancelled;

      }
      
      Cancelled{}
      
      Finished{
        cancelTrip() -> Cancelled; 
      } 
      
    }
     
}