let rec student_grade (s:student) (padd:paddress) = 
  (* Function for computing the mean over subprojects *)
  let student_grade_for_addresses (s:student) (dg:float) (pl:project list) = 
    let sadd = List.map (fun p -> p.add) pl in  
    let sgra = List.map (fun p -> (p,student_grade s p)) sadd in
    let srea = List.filter (fun (_,t) -> t>=0.) sgra in 
      if (List.length srea > 0) then 
        let scoe = List.map (fun (p,g) -> (g,(get_group_project_coeff s.group p))) srea in 
        let coef = List.fold_left (fun a b -> a +. (snd b)) 0. scoe in 
        let grad = List.fold_left (fun a b -> a +. (fst b)) 0. scoe in 
          if (coef <= 0.01) then dg else grad /. coef
      else dg in 

    do_something_group_project (fun pad2 -> 
      try 
        let s_team = H.get_assoc s.teams padd in                           
        let tnum = s_team.n in 
          try (* Case where the student has a steam and a team *)
            let team = H.get_assoc (get_project_teams pad2) tnum in
            let grad = (if (s_team.g >= 0.) then s_team.g (* Personal grade has precedence *)
                        else get_team_grade team) in 
              if (grad = (-1.)) then !(pad2.dgrad) else grad
          with Not_found -> (* Case where the student only has a s_team *)
            if (s_team.g = (-1.)) then student_grade_for_addresses s !(pad2.dgrad) !(pad2.sub)
            else s_team.g
      with Not_found -> (* Case where there there isn't even a s_team *)
        student_grade_for_addresses s !(pad2.dgrad) !(pad2.sub)) 
      (fun () -> !default_grade) (s.group) padd