<commit_before>import Chart

protocol ElevationProfilePresenterProtocol: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
  func configure()
  func onAppear()
  func onDissapear()

  func onDifficultyButtonPressed()
  func onDragBegin()
  func onZoomBegin()
  func onNavigateBegin()
  func onSelectedPointChanged(_ point: CGFloat)
}

protocol ElevationProfileViewControllerDelegate: AnyObject {
  func openDifficultyPopup()
  func updateMapPoint(_ distance: Double)
}

fileprivate struct DescriptionsViewModel {
  let title: String
  let value: UInt
  let imageName: String
}

class ElevationProfilePresenter: NSObject {
  private weak var view: ElevationProfileViewProtocol?
  private let data: ElevationProfileData
  private let delegate: ElevationProfileViewControllerDelegate?

  private let cellSpacing: CGFloat = 8
  private let descriptionModels: [DescriptionsViewModel]
  private let chartData: ElevationProfileChartData
  private let imperialUnits: Bool

  init(view: ElevationProfileViewProtocol,
       data: ElevationProfileData,
       imperialUnits: Bool,
       delegate: ElevationProfileViewControllerDelegate?) {
    self.view = view
    self.data = data
    self.imperialUnits = imperialUnits
    self.delegate = delegate
    chartData = ElevationProfileChartData(data)

    descriptionModels = [
      DescriptionsViewModel(title: L("elevation_profile_ascent"), value: data.ascent, imageName: "ic_em_ascent_24"),
      DescriptionsViewModel(title: L("elevation_profile_descent"), value: data.descent, imageName: "ic_em_descent_24"),
      DescriptionsViewModel(title: L("elevation_profile_maxaltitude"), value: data.maxAttitude, imageName: "ic_em_max_attitude_24"),
      DescriptionsViewModel(title: L("elevation_profile_minaltitude"), value: data.minAttitude, imageName: "ic_em_min_attitude_24")
    ]
  }

  deinit {
    MWMBookmarksManager.shared().resetElevationActivePointChanged()
    MWMBookmarksManager.shared().resetElevationMyPositionChanged()
  }
}

extension ElevationProfilePresenter: ElevationProfilePresenterProtocol {
  func configure() {
    view?.setDifficulty(data.difficulty)
    view?.setTrackTime("\(data.trackTime)")
    let presentationData = ChartPresentationData(chartData,
                                                 formatter: ChartFormatter(imperial: imperialUnits),
                                                 useFilter: true)
    view?.setChartData(presentationData)
    view?.setActivePoint(data.activePoint)
    view?.setMyPosition(data.myPosition)
//    if let extendedDifficultyGrade = data.extendedDifficultyGrade {
//      view?.isExtendedDifficultyLabelHidden = false
//      view?.setExtendedDifficultyGrade(extendedDifficultyGrade)
//    } else {
      view?.isExtendedDifficultyLabelHidden = true
//    }

    MWMBookmarksManager.shared().setElevationActivePointChanged(data.trackId) { [weak self] distance in
      self?.view?.setActivePoint(distance)
    }
    MWMBookmarksManager.shared().setElevationMyPositionChanged(data.trackId) { [weak self] distance in
      self?.view?.setMyPosition(distance)
    }
  }

  func onAppear() {
    Statistics.logEvent(kStatElevationProfilePageOpen,
                        withParameters: [/*kStatServerId: data.serverId,*/ //TODO: clarify
                                         kStatMethod: "info|track",
                                         kStatState: "preview"])
  }

  func onDissapear() {
    Statistics.logEvent(kStatElevationProfilePageClose,
                        withParameters: [/*kStatServerId: data.serverId,*/ //TODO: clarify
                                         kStatMethod: "swipe"])
  }

  func onDifficultyButtonPressed() {
    delegate?.openDifficultyPopup()
  }

  func onDragBegin() {
    Statistics.logEvent(kStatElevationProfilePageDrag,
                        withParameters: [/*kStatServerId: data.serverId,*/ //TODO: clarify
                                         kStatAction: "zoom_in|zoom_out|drag",
                                         kStatSide: "left|right|all"])
  }


  func onZoomBegin() {
    Statistics.logEvent(kStatElevationProfilePageZoom,
                        withParameters: [/*kStatServerId: data.serverId,*/ //TODO: clarify
                                         kStatIsZoomIn: true])
  }

  func onNavigateBegin() {
    Statistics.logEvent(kStatElevationProfilePageNavigationAction,
                        withParameters: [/*kStatServerId: data.serverId,*/ //TODO: clarify
                          :])
  }

  func onSelectedPointChanged(_ point: CGFloat) {
    let x1 = Int(floor(point))
    let x2 = Int(ceil(point))
    let d1: Double = chartData.points[x1].distance
    let d2: Double = chartData.points[x2].distance
    let dx = Double(point.truncatingRemainder(dividingBy: 1))
    let distance = d1 + (d2 - d1) * dx
    delegate?.updateMapPoint(distance)
  }
}

// MARK: - UICollectionDataSource

extension ElevationProfilePresenter {
  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return descriptionModels.count
  }

  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ElevationProfileDescriptionCell", for: indexPath) as! ElevationProfileDescriptionCell
    let model = descriptionModels[indexPath.row]
    cell.configure(title: model.title, value: "\(model.value)", imageName: model.imageName)
    return cell
  }
}

// MARK: - UICollectionViewDelegateFlowLayout

extension ElevationProfilePresenter {
  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let width = collectionView.width
    let cellHeight = collectionView.height
    let modelsCount = CGFloat(descriptionModels.count)
    let cellWidth = (width - cellSpacing * (modelsCount - 1)) / modelsCount
    return CGSize(width: cellWidth, height: cellHeight)
  }
<commit_msg>[iOS] Added units for attitude in elevation profile<commit_after>import Chart

protocol ElevationProfilePresenterProtocol: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
  func configure()
  func onAppear()
  func onDissapear()

  func onDifficultyButtonPressed()
  func onDragBegin()
  func onZoomBegin()
  func onNavigateBegin()
  func onSelectedPointChanged(_ point: CGFloat)
}

protocol ElevationProfileViewControllerDelegate: AnyObject {
  func openDifficultyPopup()
  func updateMapPoint(_ distance: Double)
}

fileprivate struct DescriptionsViewModel {
  let title: String
  let value: UInt
  let imageName: String
}

class ElevationProfilePresenter: NSObject {
  private weak var view: ElevationProfileViewProtocol?
  private let data: ElevationProfileData
  private let delegate: ElevationProfileViewControllerDelegate?

  private let cellSpacing: CGFloat = 8
  private let descriptionModels: [DescriptionsViewModel]
  private let chartData: ElevationProfileChartData
  private let formatter: ChartFormatter

  init(view: ElevationProfileViewProtocol,
       data: ElevationProfileData,
       imperialUnits: Bool,
       delegate: ElevationProfileViewControllerDelegate?) {
    self.view = view
    self.data = data
    self.delegate = delegate
    chartData = ElevationProfileChartData(data)
    formatter = ChartFormatter(imperial: imperialUnits)

    descriptionModels = [
      DescriptionsViewModel(title: L("elevation_profile_ascent"), value: data.ascent, imageName: "ic_em_ascent_24"),
      DescriptionsViewModel(title: L("elevation_profile_descent"), value: data.descent, imageName: "ic_em_descent_24"),
      DescriptionsViewModel(title: L("elevation_profile_maxaltitude"), value: data.maxAttitude, imageName: "ic_em_max_attitude_24"),
      DescriptionsViewModel(title: L("elevation_profile_minaltitude"), value: data.minAttitude, imageName: "ic_em_min_attitude_24")
    ]
  }

  deinit {
    MWMBookmarksManager.shared().resetElevationActivePointChanged()
    MWMBookmarksManager.shared().resetElevationMyPositionChanged()
  }
}

extension ElevationProfilePresenter: ElevationProfilePresenterProtocol {
  func configure() {
    view?.setDifficulty(data.difficulty)
    view?.setTrackTime("\(data.trackTime)")
    let presentationData = ChartPresentationData(chartData,
                                                 formatter: formatter,
                                                 useFilter: true)
    view?.setChartData(presentationData)
    view?.setActivePoint(data.activePoint)
    view?.setMyPosition(data.myPosition)
//    if let extendedDifficultyGrade = data.extendedDifficultyGrade {
//      view?.isExtendedDifficultyLabelHidden = false
//      view?.setExtendedDifficultyGrade(extendedDifficultyGrade)
//    } else {
      view?.isExtendedDifficultyLabelHidden = true
//    }

    MWMBookmarksManager.shared().setElevationActivePointChanged(data.trackId) { [weak self] distance in
      self?.view?.setActivePoint(distance)
    }
    MWMBookmarksManager.shared().setElevationMyPositionChanged(data.trackId) { [weak self] distance in
      self?.view?.setMyPosition(distance)
    }
  }

  func onAppear() {
    Statistics.logEvent(kStatElevationProfilePageOpen,
                        withParameters: [/*kStatServerId: data.serverId,*/ //TODO: clarify
                                         kStatMethod: "info|track",
                                         kStatState: "preview"])
  }

  func onDissapear() {
    Statistics.logEvent(kStatElevationProfilePageClose,
                        withParameters: [/*kStatServerId: data.serverId,*/ //TODO: clarify
                                         kStatMethod: "swipe"])
  }

  func onDifficultyButtonPressed() {
    delegate?.openDifficultyPopup()
  }

  func onDragBegin() {
    Statistics.logEvent(kStatElevationProfilePageDrag,
                        withParameters: [/*kStatServerId: data.serverId,*/ //TODO: clarify
                                         kStatAction: "zoom_in|zoom_out|drag",
                                         kStatSide: "left|right|all"])
  }


  func onZoomBegin() {
    Statistics.logEvent(kStatElevationProfilePageZoom,
                        withParameters: [/*kStatServerId: data.serverId,*/ //TODO: clarify
                                         kStatIsZoomIn: true])
  }

  func onNavigateBegin() {
    Statistics.logEvent(kStatElevationProfilePageNavigationAction,
                        withParameters: [/*kStatServerId: data.serverId,*/ //TODO: clarify
                          :])
  }

  func onSelectedPointChanged(_ point: CGFloat) {
    let x1 = Int(floor(point))
    let x2 = Int(ceil(point))
    let d1: Double = chartData.points[x1].distance
    let d2: Double = chartData.points[x2].distance
    let dx = Double(point.truncatingRemainder(dividingBy: 1))
    let distance = d1 + (d2 - d1) * dx
    delegate?.updateMapPoint(distance)
  }
}

// MARK: - UICollectionDataSource

extension ElevationProfilePresenter {
  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return descriptionModels.count
  }

  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ElevationProfileDescriptionCell", for: indexPath) as! ElevationProfileDescriptionCell
    let model = descriptionModels[indexPath.row]
    cell.configure(title: model.title, value: formatter.altitudeString(from: Double(model.value)), imageName: model.imageName)
    return cell
  }
}

// MARK: - UICollectionViewDelegateFlowLayout

extension ElevationProfilePresenter {
  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let width = collectionView.width
    let cellHeight = collectionView.height
    let modelsCount = CGFloat(descriptionModels.count)
    let cellWidth = (width - cellSpacing * (modelsCount - 1)) / modelsCount
    return CGSize(width: cellWidth, height: cellHeight)
  }

{'fraction_non_alphanumeric': 0.08744247205785667, 'fraction_numerical': 0.003287310979618672, 'mean_word_length': 3.3963150289017343, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 32, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4944152', 'n_tokens_mistral': 3442, 'n_tokens_neox': 3302, 'n_words': 658}