def GetRewardWeights(M, Rep=-1, alpha=Decimal('0.1')):
    if Rep == -1:
        Rep = DemocracyRep(M)
    if type(Rep[0]) == list:
        Rep = map(lambda x: x[0], Rep)
    Results = custommath.WeightedPrinComp(M, Rep)
    FirstLoading = Results['Loadings']
    FirstScore = Results['Scores']
    a = min(map(abs, FirstScore))
    b = max(FirstScore)
    Set1 = map(lambda x: x + a, FirstScore)
    Set2 = map(lambda x: x - b, FirstScore)
    Old = custommath.dot([Rep], M)
    New1 = custommath.dot([custommath.GetWeight(Set1)], M)
    New2 = custommath.dot([custommath.GetWeight(Set2)], M)

    def sub_f(a, b):
        return a - b

    def f(n):
        return sum(map(lambda x: x**2, map(sub_f, n[0], Old[0])))

    RefInd = f(New1) - f(New2)
    if (RefInd <= 0): AdjPrinComp = Set1
    else: AdjPrinComp = Set2
    RowRewardWeighted = Rep
    if max(map(abs, AdjPrinComp)) != 0:
        m = custommath.mean(Rep)
        RRW = []
        for i in range(len(Rep)):
            RRW.append(AdjPrinComp[i] * Rep[i] / m)
        RowRewardWeighted = custommath.GetWeight(RRW)
    SmoothedR = []
    for i in range(len(Rep)):
        SmoothedR.append(alpha * RowRewardWeighted[i] + (1 - alpha) * Rep[i])
    Out = {
        "FirstL": FirstLoading,
        "OldRep": Rep,
        "ThisRep": RowRewardWeighted,
        "SmoothRep": SmoothedR
    }
    return (Out)
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