9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

クソアプリAdvent Calendar 2023

Day 19

外に出ない自分を罵倒してくれるアプリを作った

Last updated at Posted at 2023-12-18

この記事はQiita クソアプリ Advent Calendar 2023 シリーズ2 19日目の記事です。

初めに

フルリモートで働いているエンジニアの皆さんは、ほとんどが家で働いていることが多くて、
外に出ないことがあるのではないでしょうか?

自分も例に漏れずに、ずっとデスクの前にいて、全く歩かない日があります。

歩数.jpeg
圧倒的歩数、!

これではダメだ、外に出ないと、!
だけど外に出なくても叱ってくれる人もいない、外に出ない日は罵倒されたい、いや、罵倒してほしい
だけど時々褒めて欲しい

ということで、
その日に歩いた歩数をもとに罵倒してくれつつ(時々褒める)明日の運勢を占ってくれるアプリを作りました

ソースコードはこちら

デモ

15歩しか歩いていないので、圧倒的な悪口、、!ありがとうございます。

ちなみにたくさん歩くと、こんなふうに褒めてくれます。

中身

中身は単純で、HealthKitで当日の歩数を取得して、それをもとにOpen AIのAPIを叩いています。

HealthKitUseCase.swift

final class HealthKitUseCaseImpl: HealthKitUseCase {

    ~~~省略~~~
    func fetchTodayStepCount(completion: @escaping (Result<Int, Error>) -> Void) {
        // 当日の今までの歩数を取得する
        let distanceType = HKObjectType.quantityType(forIdentifier: .stepCount)!
        let now = Date()
        let startOfDay = Calendar.current.startOfDay(for: now)
        let predicate = HKQuery.predicateForSamples(withStart: startOfDay, end: now, options: .strictStartDate)
        let query = HKStatisticsQuery(quantityType: distanceType, quantitySamplePredicate: predicate) { query, statistics, error in
            guard let stepCount = statistics?.sumQuantity()?.doubleValue(for: HKUnit.count()) else { return }
            if let error = error {
                completion(.failure(error))
                return
            }
            completion(.success(Int(stepCount)))
        }
        healthStore.execute(query)
    }
}

歩数の取得

StepCountRange.swift
enum StepCountRange {
    case veryHigh
    case high
    case middle
    case low
    case veryLow

    init(stepCount: Int) {
        switch stepCount {
        case 0...100:
            self = .veryLow
        case 101...1000:
            self = .low
        case 1001...3000:
            self = .middle
        case 3001...6000:
            self = .high
        default:
            self = .veryHigh
        }
    }

  var prompt: String {
        switch self {
        case .veryHigh:
            return "あなたの運命は大吉ですから始めて、最高にすごいので、人生最大級くらいの褒め言葉を送ってください。実際の名言を教えて欲しい。今日1日を幸せに終わりたい"
        case .high:
            return "あなたの運命は中吉ですから始めて、少し良いので、ちょっとだけ褒めてください。最後に人生の格言みたいなことを言ってください"
        case .middle:
            return "あなたの運命は小吉ですから始めて、まあまあなので、適当に人生の格言っぽいことを言ってください"
        case .low:
            return "あなたの運命は凶ですから始めて、あんまり良くないので、ちょっと罵倒してください。あと適当に人生の格言っぽいことを言ってください"
        case .veryLow:
            return "あなたの運命は大凶ですから始めて、話にならないくらい罵倒してパワハラ上司並みに詰めてください。"
        }
    }
}

取得した歩数をもとにレンジを設けて、それをもとにプロンプトを作成してます。

ChatGPTRepository.swift
final class ChatGPTRepositoryImpl: ChatGPTRepository {

    ~~~省略~~~
    func fetchTalkStreaming(chatQuery: ChatQuery) -> AsyncThrowingStream<ChatStreamResult, Error> {
        openAI.chatsStream(query: chatQuery)
    }
}

徐々に表示された方が体験として良いので、Streamで流しています。
OpenAIのAPIは最初は自作してましたが、便利なライブラリがあることに気がついて乗り換えました。

終わり

もはやどこに占い要素があるのか?という感じですが、これで健康的な生活が送れそうです。
開発を経て、悪口のボキャブラリーも増やすことができました。

参考

全体のコード

OpenAIのドキュメント

HealthKit

終わり!

9
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?