def FillNa(Mna, Rep, Catchp=Decimal('0.1')):
    Mnew = Mna
    MnewC = Mna
    if any_NA(Mna):
        DecisionOutcomesRaw = GetDecisionOutcomes(Mna, Rep)
        NAmat = map(lambda row: map(lambda x: 1 if x == 'NA' else 0, row), Mna)
        Mnew = map(lambda row: map(lambda x: 0 if x == 'NA' else x, row), Mna)
        NAsToFill = custommath.dot(NAmat, diag(DecisionOutcomesRaw))
        for row in range(len(Mnew)):
            for i in range(len(Mnew[row])):
                Mnew[row][i] = Mnew[row][i] + NAsToFill[row][i]
        return (map(
            lambda row: map(lambda x: custommath.Catch(x, Catchp), row), Mnew))
    return (Mna)
def Factory(M0, Rep, CatchP=Decimal('0.1'), MaxRow=5000):
    Rep = custommath.ReWeight(Rep)
    Filled = FillNa(M0, Rep, CatchP)
    PlayerInfo = GetRewardWeights(Filled, Rep, Decimal('0.1'))
    AdjLoadings = PlayerInfo['FirstL']
    #print('smoothrep: ' +str(PlayerInfo['SmoothRep']))#way wrong
    #print('Filled: ' +str(Filled))
    DecisionOutcomesRaw = custommath.dot([PlayerInfo['SmoothRep']], Filled)[0]
    #print('raw outcomes: ' +str(DecisionOutcomesRaw))
    DecisionOutcomeAdj = map(lambda x: custommath.Catch(x, CatchP),
                             DecisionOutcomesRaw)
    Certainty = map(lambda x: 2 * (x - Decimal('0.5')), DecisionOutcomesRaw)
    Certainty = map(abs, Certainty)
    ConReward = custommath.GetWeight(Certainty)
    Avg_Certainty = custommath.mean(Certainty)
    DecisionOutcomeAdj = []
    for i, raw in enumerate(DecisionOutcomesRaw):
        DecisionOutcomeAdj.append(custommath.Catch(raw, CatchP))
    DecisionOutcomeFinal = DecisionOutcomeAdj
    NAmat = map(
        lambda row: map(lambda x: 1
                        if type(x) in [str, unicode] else 0, row), M0)
    a = custommath.dot([PlayerInfo['SmoothRep']], NAmat)[0]
    ParticipationC = map(lambda x: 1 - x, a)
    v = map(sum, NAmat)
    ParticipationR = map(lambda x: 1 - x / Decimal(len(NAmat[0])), v)
    PercentNA = 1 - custommath.mean(ParticipationC)
    NAbonusR = custommath.GetWeight(ParticipationR)

    def plus(a, b):
        return a + b

    RowBonus = map(plus, map(lambda x: x * PercentNA, NAbonusR),
                   map(lambda x: x * (1 - PercentNA), PlayerInfo['SmoothRep']))
    NAbonusC = custommath.GetWeight(ParticipationC)
    ColBonus = map(plus, map(lambda x: x * PercentNA, NAbonusC),
                   map(lambda x: x * (1 - PercentNA), ConReward))
    namatsum = []
    for i in range(len(NAmat[0])):
        namatsum.append(sum(map(lambda x: x[i], NAmat)))
    Output = {
        'Original': M0,
        'Filled': Filled,
        'Agents': {
            'OldRep': PlayerInfo['OldRep'],  #[0],
            'ThisRep': PlayerInfo['ThisRep'],
            'SmoothRep': PlayerInfo['SmoothRep'],
            'NArow': map(sum, NAmat),  #.sum(axis=1).base,
            'ParticipationR': ParticipationR,  #.base,
            'RelativePart': NAbonusR,  #.base,
            'RowBonus': RowBonus,  #.base,
        },
        'Decisions': {
            'First Loading': AdjLoadings,
            'DecisionOutcomes_Raw': DecisionOutcomesRaw,
            'Consensus Reward': ConReward,
            'Certainty': Certainty,
            'NAs Filled': namatsum,  #NAmat.sum(axis=0),
            'ParticipationC': ParticipationC,
            'Author Bonus': ColBonus,
            'DecisionOutcome_Final': DecisionOutcomeFinal,
        },
        'Participation': 1 - PercentNA,
        'Certainty': Avg_Certainty,
    }
    return Output