Modifiy child constantly by using the UploadDate - ios

I am currently building an Instagram clone.
I am quit new so please forgive me if this question is answered easily.
I just want to have a specific score attached to each post.
I already managed to give each new post a score 0f 0 to start with and each time its liked it increases by 100, disliked it decreases by 100.
for every comment it grows by 50 points.
Because I want to order them smartly and want it to show different posts at the top over time I wanted to include a third variable which influences the score.
I want it to decrease the score by -10 each hour since its been uploaded.
The increase and decrease is done in my function incrementLikes() /incrementComments() .
I know that I can't modify the value of score for the time since its uploaded there, but I don't know where else.
My date extension (prob where I can do it?)
extension Date {
func timeAgoDisplay() -> String {
let secondsAgo = Int(Date().timeIntervalSince(self))
let minute = 60
let hour = 60 * minute
let day = hour * 24
let week = day * 7
let month = week * 4
let quotient : Int
let unit: String
if secondsAgo < minute {
quotient = secondsAgo
unit = "Sekunde"
} else if secondsAgo < hour {
quotient = secondsAgo / minute
unit = "Minute"
} else if secondsAgo < day {
quotient = secondsAgo / hour
unit = "Stunde"
} else if secondsAgo < week {
quotient = secondsAgo / day
unit = "Tage"
} else if secondsAgo < month {
quotient = secondsAgo / week
unit = "Woche"
} else {
quotient = secondsAgo / month
unit = "Monat"
}
return "Vor \(quotient) \(unit)\(quotient == 1 ? "" : "n")"
}
}
my function in homeTableViewCell where I set the date
func updateView() {
captionLabel.userHandleLinkTapHandler = { label,string, range in
let mention = String(string.characters.dropFirst())
API.User.observeUserByUsername(username: mention.lowercased(), completion: { (user) in
self.delegate?.goToProfileUserViewController(userId: user.id!)
})
}
guard let count = post?.commentCount else {return}
if count == 0 {
commentButton.setTitle("Schreibe den ersten Kommentar", for: UIControlState.normal)
}else if count == 1 {
commentButton.setTitle("Sieh dir den ersten Kommentar an", for: UIControlState.normal)
} else {
commentButton.setTitle("Alle \(count) Kommentare ansehen", for: UIControlState.normal)
}
let timeAgoDisplay = post?.creationDate?.timeAgoDisplay()
timeLabel.text = timeAgoDisplay
}
thanks for your help :)

The idea of updating the score every hour using a time is based on the idea that the app is constantly running, which seems flawed.
You could instead have something like
var score: Int {
return likes*100 - dislikes*100 + comments*50 - hoursSinceUpload()*10
}
where hoursSinceUpload is computed by something like (see Getting the difference between two NSDates in (months/days/hours/minutes/seconds) for reference)
func hoursSinceUpload() -> Int {
return Calendar.current.dateComponents([.hour], from: uploadDate, to: Date()).hour
}

Related

How to compare two string values within a threshold value in swift?

I am trying to write a code where I have got two time[hh:min] data(String type). Need to just compare but the challenge is my code undergones some validations before returning the final values. so the assertion fails sometimes stating expected value is [17:04] but actual is [17:05]. Is there any way where we can use concept of Threshold that upto few minutes (say 2 mins) the comparison will still be valid?
Step one is do not store a thing as something that it is not. If these are times, they should be stored as times. Strings are for representation to the users; underlying storage is for reality.
So now let's store our times as date components:
let t1 = DateComponents(hour:17, minute:4)
let t2 = DateComponents(hour:17, minute:5)
Now it's easy to find out how far apart they are:
let cal = Calendar(identifier: .gregorian)
if let d1 = cal.date(from: t1),
let d2 = cal.date(from: t2) {
let diff = abs(d1.timeIntervalSince(d2))
// and now decide what to do
}
You first need to seprate your string to an array, and then you can compare.
/* That two arrays are A1 and A2 */
let minute1 = Int(A1[0])*60+Int(A1[1])
let minute2 = Int(A2[0])*60+Int(A2[1])
This may help you. I think that #Sweeper did not understand that it is a time, not a date.
You can convert your string to minutes, subtract one from another and check if the absolute value is less than the threshold:
extension String {
var time24hToMinutes: Int? {
guard count == 5, let hours = Int(prefix(2)), let minutes = Int(suffix(2)), Array(self)[2] == ":" else { return nil }
return hours * 60 + minutes
}
func time24hCompare(to other: String, threshold: Int = 2) -> Bool {
guard let lhs = time24hToMinutes, let rhs = other.time24hToMinutes else { return false }
return abs(lhs-rhs) < threshold
}
}
Testing:
"17:02".time24hCompare(to: "17:04") // false
"17:03".time24hCompare(to: "17:04") // true
"17:04".time24hCompare(to: "17:04") // true
"17:05".time24hCompare(to: "17:04") // true
"17:06".time24hCompare(to: "17:04") // false

automatically update label every week

So I was wondering, how could I update a specific label once every week. I have a recipe app and want to present the user with new recipe once a week, i would get the recipe name from an Array
var recipeArray = ["Pasta, Fish, Meatballs"]
var weekNumber = 0
func weeklyRecipe () {
//trigger once a week
if weekNumber <= (recipeArray.count - 1) {
weekNumber += 1
} else {
weekNumber = 0
}
label.text = recipeArray[weekNumber]
}
I have no idea how to work with calendar, and will appreciate any help on the topic.
You can update recipe on any particular day. Suppose you want to update on Sunday. Then
let weekday = Calendar.current.component(.weekday, from: Date())
if weekday == 1 {
// Code for updation
}

Time interval not changing after repeated function call

The goal of my code is to call a function every 5 seconds, which it succeeds in doing so. The issue is that when I declare my seconds variable every time, it does not change even though the start date should not be changing.
func timedUpdate()
{
let initialBank = 2000
let dateOfInstallation = UserDefaults.standard.object(forKey: "installDate")
let seconds = date.timeIntervalSince(dateOfInstallation as! Date) / 8.64
let bestStreak = (UserDefaults.standard.integer(forKey: "bestStreak"))
let days = seconds / 86400
print(seconds/8.64)
print(UserDefaults.standard.object(forKey: "bestStreak")!)
if (Int(days) > bestStreak)
{
UserDefaults.standard.set(days, forKey: "bestStreak")
}
bestStreakLabel.text = "\(Int(bestStreak)) Days"
currentStreakLabel.text = "\(Int(days)) Days"
currentStreakBar.progress = CGFloat(Float(days)/Float(bestStreak))
bestStreakBar.progress = 1
getTodaysSteps { [weak self] steps in
self?.bankTotalLabel.text = "\(Int(steps) - Int(seconds/8.64) + Int(initialBank))"
self?.circleLabel.progress = Double(((Double(steps) - Double(seconds) + Double(initialBank))) / 10000)
if (Int(steps) - Int(seconds) + Int(initialBank) < 0)
{
// Will Eventually need a popup screen here to say you lost and streak is reset to 0
self?.resetApp()
}
}
}
When I print the value of seconds, it is always the same decimal, very close to 0. Thank you in advance for the help!

How to determine if a business is open given the hours of operation (Swift-iOS)

I have an app that I'm building in Swift that needs to determine if a store/restaurant is currently open. It queries a database that I have control of, so I can set the open hours however I'd like. Currently I have an openTime/closeTime column for each day of the week set as a timestamp. For example: MonOpen = 11:00, MonClose = 19:00.
How can I use swift to determine if the place of business is currently open? I'm imagining something like if currentTime > MonOpen & currentTime < MonClose {...
An example of this is the iOS Starbucks app. If you go to locations, each location is listed with an "Open until 22:00" or "Open until 23:00."
It's just a matter of playing with the timezone, whether you use the user system's timezone or let them choose another one in the app's settings:
let tz = NSTimeZone.defaultTimeZone()
let now = NSCalendar.currentCalendar().componentsInTimeZone(tz, fromDate: NSDate())
if now.weekDay == 2 && now.hour > MonOpen && now.hour < MonClose {
// The store is open
}
I would like to take another crack at this question since we now have Swift 5.1 and most businesses have more complex opening times than just in hours.
import Foundation
// There might be an enum in Swift
// that I did not bother to lookup
enum Days : Int {
case Sun = 1
case Mon = 2
case Tue = 3
case Wed = 4
case Thu = 5
case Fri = 6
case Sat = 7
}
func isOfficeOpenNow(weekSchedule: [Days: (Int, Int)]) -> Bool {
let tz = NSTimeZone.default
let now = NSCalendar.current.dateComponents(in: tz, from: Date())
guard let weekday = now.weekday,
let today = Days(rawValue: weekday),
let hour = now.hour,
let minute = now.minute else {
return false
}
guard let todayTuple = weekSchedule[today] else {
return false // no key, means closed
}
let opensAt = todayTuple.0
let closesAt = todayTuple.1
assert(opensAt < closesAt, "Your schedule is setup wrong.")
let rightNowInMinutes = hour * 60 + minute
return rightNowInMinutes > opensAt &&
rightNowInMinutes < closesAt
}
To use this just define a dictionary for each day.
Key is the dayofweek. Could have used a string "Mon","Tue",etc
but then you will need a mapping or DateFormatter
Value is a tuple (int, int) for (open, close) in minutes
Using minutes, as many stores have more complex open
closing times than just hours
let schedule = [
Days.Mon: (9*60+30, 22*60+30),
Days.Tue: (9*60+30, 23*60+05),
Days.Wed: (9*60+30, 22*60+30),
Days.Thu: (9*60+30, 22*60+30),
Days.Fri: (9*60+30, 22*60+30),
]
if isOfficeOpenNow(weekSchedule: schedule) {
print("Store open")
} else {
print("Store closed")
}
If a specific week is a holiday, just update the schedule for the week and all is good with the world.
If a day is closed, just remove the key from the schedule.

Quickblox User online status IOS

I have been using quickblox sdk for IOS and i have one query regarding user's online status.
Below is the code which is recommended.
QBUUser *user = ...;
NSInteger currentTimeInterval = [[NSDate date] timeIntervalSince1970];
NSInteger userLastRequestAtTimeInterval = [[user lastRequestAt] timeIntervalSince1970];
// if user didn't do anything last 1 minute (60 seconds)
if((currentTimeInterval - userLastRequestAtTimeInterval) > 60)
{
// user is offline now
}
But my query is that do i need to check this in a timer event because every 5-10 seconds i would want to know if user is online or there is any other better approach?
Kudi, the only way to find out the last date of user's request is by using QBUUser lastRequestAt.
Here is my custom function to know user's presence. I set a timer which runs every 10 seconds.
func update() {
let currentTimeInterval: Int = Int(NSDate().timeIntervalSince1970)
var userlastrew = Int()
let rid = UInt(dialog.recipientID)
var differ = Int()
QBRequest.userWithID(rid, successBlock: { (response : QBResponse, user: QBUUser?) -> Void in
userlastrew = Int((user?.lastRequestAt?.timeIntervalSince1970)!)
differ = currentTimeInterval - userlastrew
if differ > 120 {
let (d,h,m) = self.secondsToHoursMinutesSeconds(differ)
var txt = String()
if (d <= 0) {
if (m > 60 && h > 1 ) {
txt = "Last online \(h) hours ago"
}
if (m >= 60 && h == 1) {
txt = "Last online \(h) hour ago"
}
if (m < 60 && h < 1) {
txt = "Last online \(m) minutes ago"
}
if (m < 60 && h == 1) {
txt = "Last online \(h) hour ago"
}
if (m < 60 && h > 1) {
txt = "Last online \(h) hours ago"
}
} else {
if (d > 1) {
txt = "Last online \(d) days ago"
} else {
txt = "Last online \(d) day ago"
}
}
//user is offline
} else {
//user is online
}
}, errorBlock: {(response: QBResponse) -> Void in
// Handle error
})
}
func secondsToHoursMinutesSeconds (seconds : Int) -> (Int, Int, Int) {
return (seconds / 86400, seconds / 3600, (seconds % 3600) / 60)
}

Resources