def calculate_ri_to_earn_in(contributorScoresWithEnrollment: pd.DataFrame) -> pd.DataFrame:
  """
  A function that updates rating impact needed to earn in for earned out users
  Args:
      contributorScoresWithEnrollment (pd.DataFrame): contributor scores with state and current enrollment
  Returns:
    pd.DataFrame: dataframe with updated rating impact required to earn in for earned out users
  """
  earnedOutUsers = (
    contributorScoresWithEnrollment[c.enrollmentState]
    == c.enrollmentStateToThrift[c.earnedOutNoAcknowledge]
  )

  contributorScoresWithEnrollment.loc[
    earnedOutUsers, c.successfulRatingNeededToEarnIn
  ] = contributorScoresWithEnrollment.apply(
    lambda row: c.ratingImpactForEarnIn
    + max([row[c.ratingImpact], 0])
    + (c.ratingImpactForEarnIn * max(row[c.numberOfTimesEarnedOutKey] - 1, 0)),
    axis=1,
  ).loc[earnedOutUsers]

  # for top writers, overwrite the score required to earn in with non-escalating version
  topWriters = is_top_writer(contributorScoresWithEnrollment)

  contributorScoresWithEnrollment.loc[
    (earnedOutUsers) & (topWriters), c.successfulRatingNeededToEarnIn
  ] = contributorScoresWithEnrollment.apply(
    lambda row: c.ratingImpactForEarnIn + max([row[c.ratingImpact], 0]),
    axis=1,
  ).loc[(earnedOutUsers) & (topWriters)]

  contributorScoresWithEnrollment.loc[
    earnedOutUsers, c.enrollmentState
  ] = c.enrollmentStateToThrift[c.earnedOutAcknowledged]

  return contributorScoresWithEnrollment.drop(columns=[c.ratingImpact])

  A function that updates rating impact needed to earn in for earned out users
  Args:
      contributorScoresWithEnrollment (pd.DataFrame): contributor scores with state and current enrollment
  Returns:
    pd.DataFrame: dataframe with updated rating impact required to earn in for earned out users
  
sourcecode/scoring/contributor_state.py