seekia/internal/desires/myDesireStatistics/myDesireStatistics.go

332 lines
11 KiB
Go
Raw Normal View History

// myDesireStatistics provides functions to calculate a user's mate desire statistics
// These are statistics about a user's mate desires.
// For each desire, we calculate:
// -The number/percentage of all downloaded profiles who pass the desire
// -The number/percentage of a user's matches who pass the desire (excluding the desire)
package myDesireStatistics
//TODO: Add desire statistics about how many users fulfill each desire
// This would enable users to view fulfillment statistics without requiring them to enable FilterAll and RequireResponse for each desire
import "seekia/internal/appMemory"
import "seekia/internal/badgerDatabase"
import "seekia/internal/desires/myMateDesires"
import "seekia/internal/helpers"
import "seekia/internal/myBlockedUsers"
import "seekia/internal/myIdentity"
import "seekia/internal/profiles/viewableProfiles"
import "errors"
//Outputs:
// -int64: Number of downloaded mate identities with a viewable profile
// -int64: Number of mate identities whose viewable profile passes desire
// -float64: Percentage of all mate identities whose viewable profile passes desire
// -int64: Number of matches (Excluding input desire)
// -int64: Number of matches
// -float64: Percentage of all matches (excluding input desire) that pass input desire
// -error
func GetMyDesireStatistics(desireName string, networkType byte)(int64, int64, float64, int64, int64, float64, error){
isValid := helpers.VerifyNetworkType(networkType)
if (isValid == false){
networkTypeString := helpers.ConvertByteToString(networkType)
return 0, 0, 0, 0, 0, 0, errors.New("GetMyDesireStatistics called with invalid networkType: " + networkTypeString)
}
myIdentityExists, myIdentityHash, err := myIdentity.GetMyIdentityHash("Mate")
if (err != nil) { return 0, 0, 0, 0, 0, 0, err }
mateIdentityHashesList, err := badgerDatabase.GetAllProfileIdentityHashes("Mate")
if (err != nil) { return 0, 0, 0, 0, 0, 0, err }
numberOfMateIdentities := int64(0)
numberOfMateIdentitiesWhoPassDesire := int64(0)
numberOfMatches := int64(0)
numberOfMatchesExcludingDesire := int64(0)
for _, peerIdentityHash := range mateIdentityHashesList{
if (myIdentityExists == true && peerIdentityHash == myIdentityHash){
continue
}
userIsBlocked, _, _, _, err := myBlockedUsers.CheckIfUserIsBlocked(peerIdentityHash)
if (err != nil) { return 0, 0, 0, 0, 0, 0, err }
if (userIsBlocked == true){
// We don't include blocked users in our statistics calculation
// This is because "Blocked" is not a desire, so it won't be shown on the Desire Statistics page
// We show the user how many users they have blocked on the Match Statistics page
continue
}
profileExists, _, getAnyProfileAttributeFunction, err := viewableProfiles.GetRetrieveAnyNewestViewableUserProfileAttributeFunction(peerIdentityHash, networkType, true, false, true)
if (err != nil) { return 0, 0, 0, 0, 0, 0, err }
if (profileExists == false) {
// Profile must have been deleted, or user's profile is not viewable
continue
}
exists, _, _, err := getAnyProfileAttributeFunction("Disabled")
if (err != nil) { return 0, 0, 0, 0, 0, 0, err }
if (exists == true){
// Profile is disabled
continue
}
numberOfMateIdentities += 1
userPassesMyDesire, err := myMateDesires.CheckIfMateProfilePassesMyDesire(desireName, getAnyProfileAttributeFunction)
if (err != nil) { return 0, 0, 0, 0, 0, 0, err }
if (userPassesMyDesire == true){
numberOfMateIdentitiesWhoPassDesire += 1
}
userIsAMatchExcludingDesire, err := myMateDesires.CheckIfMateProfilePassesAllMyDesires(true, desireName, getAnyProfileAttributeFunction)
if (err != nil) { return 0, 0, 0, 0, 0, 0, err }
if (userIsAMatchExcludingDesire == false){
continue
}
numberOfMatchesExcludingDesire += 1
if (userPassesMyDesire == true){
numberOfMatches += 1
}
}
getPercentageOfMateIdentitiesWhoPassDesire := func()float64{
if (numberOfMateIdentities == 0){
return 0
}
percentageOfMateIdentitiesWhoPassDesire := 100 * (float64(numberOfMateIdentitiesWhoPassDesire)/float64(numberOfMateIdentities))
return percentageOfMateIdentitiesWhoPassDesire
}
percentageOfMateIdentitiesWhoPassDesire := getPercentageOfMateIdentitiesWhoPassDesire()
getPercentageOfMatchesWhoPassDesire := func()float64{
if (numberOfMatchesExcludingDesire == 0){
return 0
}
percentageOfMatchesWhoPassDesire := 100 * (float64(numberOfMatches)/float64(numberOfMatchesExcludingDesire))
return percentageOfMatchesWhoPassDesire
}
percentageOfMatchesWhoPassDesire := getPercentageOfMatchesWhoPassDesire()
return numberOfMateIdentities, numberOfMateIdentitiesWhoPassDesire, percentageOfMateIdentitiesWhoPassDesire, numberOfMatchesExcludingDesire, numberOfMatches, percentageOfMatchesWhoPassDesire, nil
}
type DesireStatisticsItem struct{
// Example: "Age"
DesireName string
// This is the number of mate identities who pass the desire
// Their newest viewable profile is used to check if they pass the desire
NumberOfUsersWhoPassDesire int64
// This is the percentage of mate identities who pass the desire
// Blocked and disabled users are excluded from the denominator.
PercentageOfUsersWhoPassDesire float64
// This is the number of matches the user would have if this desire was excluded
NumberOfDesireExcludedMatches int64
// This is the percentage of desire-excluded matches who pass this desire
PercentageOfDesireExcludedMatchesWhoPassDesire float64
}
//Outputs:
// -int64: Number of mate identities
// -int64: Number of matches
// -[]DesireStatisticsItem
// -error
func GetAllMyDesireStatistics(progressIdentifier string, networkType byte)(int64, int64, []DesireStatisticsItem, error){
isValid := helpers.VerifyNetworkType(networkType)
if (isValid == false){
networkTypeString := helpers.ConvertByteToString(networkType)
return 0, 0, nil, errors.New("GetAllMyDesireStatistics called with invalid networkType: " + networkTypeString)
}
myIdentityExists, myIdentityHash, err := myIdentity.GetMyIdentityHash("Mate")
if (err != nil) { return 0, 0, nil, err }
mateIdentityHashesList, err := badgerDatabase.GetAllProfileIdentityHashes("Mate")
if (err != nil) { return 0, 0, nil, err }
numberOfPeerIdentitiesString := helpers.ConvertIntToString(len(mateIdentityHashesList))
numberOfMateIdentities := int64(0)
numberOfMatches := int64(0)
//Map Structure: Desire name -> Number of mate identities who pass desire
numberOfMateIdentitiesWhoPassDesireMap := make(map[string]int64)
//Map Structure: Desire name -> Number of matches the user would have excluding the desire
numberOfDesireExcludedMatchesMap := make(map[string]int64)
for index, peerIdentityHash := range mateIdentityHashesList{
progressIndex := helpers.ConvertIntToString(index + 1)
newProgressString := "Calculated " + progressIndex + "/" + numberOfPeerIdentitiesString + " Users"
appMemory.SetMemoryEntry(progressIdentifier, newProgressString)
if (myIdentityExists == true && peerIdentityHash == myIdentityHash){
continue
}
userIsBlocked, _, _, _, err := myBlockedUsers.CheckIfUserIsBlocked(peerIdentityHash)
if (err != nil) { return 0, 0, nil, err }
if (userIsBlocked == true){
// We don't include blocked users in our statistics calculation
// This is because "Blocked" is not a desire, so it won't be shown on the Desire Statistics page
// We show the user how many users they have blocked on the Match Statistics page
continue
}
profileExists, _, getAnyProfileAttributeFunction, err := viewableProfiles.GetRetrieveAnyNewestViewableUserProfileAttributeFunction(peerIdentityHash, networkType, true, false, true)
if (err != nil) { return 0, 0, nil, err }
if (profileExists == false) {
// Profile must have been deleted, or user's profile is not viewable
continue
}
exists, _, _, err := getAnyProfileAttributeFunction("Disabled")
if (err != nil) { return 0, 0, nil, err }
if (exists == true){
// Profile is disabled
continue
}
numberOfMateIdentities += 1
userPassesMyDesiresMap, err := myMateDesires.GetMateProfilePassesAllMyDesiresMap(getAnyProfileAttributeFunction)
if (err != nil) { return 0, 0, nil, err }
getUserIsAMatchBool := func()bool{
for _, userPassesDesire := range userPassesMyDesiresMap{
if (userPassesDesire == false){
return false
}
}
return true
}
userIsAMatch := getUserIsAMatchBool()
if (userIsAMatch == true){
numberOfMatches += 1
}
for desireName, userPassesDesire := range userPassesMyDesiresMap{
if (userPassesDesire == true){
numberOfMateIdentitiesWhoPassDesireMap[desireName] += 1
}
// Now we find out if user would be a match excluding the current desire
getUserIsAMatchExcludingCurrentDesireBool := func()bool{
if (userIsAMatch == true){
return true
}
for desireNameInner, userPassesDesireInner := range userPassesMyDesiresMap{
if (desireNameInner == desireName){
continue
}
if (userPassesDesireInner == false){
return false
}
}
return true
}
userIsAMatchExcludingCurrentDesire := getUserIsAMatchExcludingCurrentDesireBool()
if (userIsAMatchExcludingCurrentDesire == true){
numberOfDesireExcludedMatchesMap[desireName] += 1
}
}
}
allMyDesiresList := myMateDesires.GetAllMyDesiresList(false)
allMyDesireStatisticsItemsList := make([]DesireStatisticsItem, 0, len(allMyDesiresList))
for _, desireName := range allMyDesiresList{
getNumberOfMateIdentitiesWhoPassDesire := func()int64{
numberOfMateIdentitiesWhoPassDesire, exists := numberOfMateIdentitiesWhoPassDesireMap[desireName]
if (exists == false) {
return 0
}
return numberOfMateIdentitiesWhoPassDesire
}
numberOfMateIdentitiesWhoPassDesire := getNumberOfMateIdentitiesWhoPassDesire()
getNumberOfDesireExcludedMatches := func()int64{
numberOfDesireExcludedMatches, exists := numberOfDesireExcludedMatchesMap[desireName]
if (exists == false) {
return 0
}
return numberOfDesireExcludedMatches
}
numberOfDesireExcludedMatches := getNumberOfDesireExcludedMatches()
getPercentageOfMateIdentitiesWhoPassDesire := func()float64{
if (numberOfMateIdentities == 0){
return 0
}
percentageOfMateIdentitiesWhoPassDesire := 100 * (float64(numberOfMateIdentitiesWhoPassDesire)/float64(numberOfMateIdentities))
return percentageOfMateIdentitiesWhoPassDesire
}
percentageOfMateIdentitiesWhoPassDesire := getPercentageOfMateIdentitiesWhoPassDesire()
getPercentageOfDesireExcludedMatchesWhoPassDesire := func()float64{
if (numberOfDesireExcludedMatches == 0){
return 0
}
percentageOfDesireExcludedMatchesWhoPassDesire := 100 * (float64(numberOfMatches)/float64(numberOfDesireExcludedMatches))
return percentageOfDesireExcludedMatchesWhoPassDesire
}
percentageOfDesireExcludedMatchesWhoPassDesire := getPercentageOfDesireExcludedMatchesWhoPassDesire()
newDesireStatisticsItem := DesireStatisticsItem{
DesireName: desireName,
NumberOfUsersWhoPassDesire: numberOfMateIdentitiesWhoPassDesire,
PercentageOfUsersWhoPassDesire: percentageOfMateIdentitiesWhoPassDesire,
NumberOfDesireExcludedMatches: numberOfDesireExcludedMatches,
PercentageOfDesireExcludedMatchesWhoPassDesire: percentageOfDesireExcludedMatchesWhoPassDesire,
}
allMyDesireStatisticsItemsList = append(allMyDesireStatisticsItemsList, newDesireStatisticsItem)
}
return numberOfMateIdentities, numberOfMatches, allMyDesireStatisticsItemsList, nil
}