Mici funcții R inutile-utile – Simulator de plante de birou

URMĂREȘTE-NE
16,065FaniÎmi place
1,142CititoriConectați-vă

(Acest articol a fost publicat pentru prima dată pe R – TomazTsqlși cu amabilitate a contribuit la R-bloggeri). (Puteți raporta problema legată de conținutul acestei pagini aici)


Doriți să vă distribuiți conținutul pe R-bloggeri? dați clic aici dacă aveți un blog, sau aici dacă nu aveți.

De data aceasta, vom crea un simulator de plante Desk. Și pentru asta avem nevoie de un set de funcții diferite 🙂

Da, vom crește o plantă R într-un joc de simulare cu o mulțime de twerks și pietre prețioase ascunse și artă ASCII 🙂🙂

Și cum funcționează cu adevărat acest set de funcții?

Stocarea progresului zilnic într-un RDS. Înainte de a rula un set de funcții, veți pregăti o locație pentru a stoca fișierul RDS (variabilele de mediu și jocul)

Arta ASCII a fost realizată de GPT pentru toate etapele și este atât de drăguță 🙂🙂

plant_art <- list(    # Stage 0: Seed  seed = c(    "            ",    "            ",    "            ",    "            ",    "     .      ",    "    (.)     ",    "   -----    ",    "  |     |   ",    "  |~~~~~|   ",    "  |_____|   "  ),    # Stage 1: Sprout  sprout = c(    "            ",    "            ",    "            ",    "     ,      ",    "    (')     ",    "     |      ",    "   -----    ",    "  |     |   ",    "  |~~~~~|   ",    "  |_____|   "  ),    # Stage 2: Seedling  seedling = c(    "            ",    "            ",    "     \|/    ",    "    \|||/   ",    "     |||    ",    "     |||    ",    "   -----    ",    "  |     |   ",    "  |~~~~~|   ",    "  |_____|   "  ),    # Stage 3: Young plant  young = c(    "            ",    "    \~~/    ",    "   \\|//   ",    "    \|/     ",    "    |||     ",    "    |||     ",    "   -----    ",    "  |     |   ",    "  |~~~~~|   ",    "  |_____|   "  ),......

Apoi veți avea la dispoziție funcții de ajutor și principale. Codul complet este disponibil în depozitul meu Github.

Pentru a rula jocul, va trebui să plantezi o nouă plantă, să o udați, să verificați starea plantei și multe altele.

Iată un extras din cod:

hline <- function(char = "═", n = 40) strrep(char, n)

# get current status of a plant / game play
get_plant <- function(file = .plant_file) {
  if (file.exists(file)) { readRDS(file) } 
}


# Save plant in RDS and all game play!
save_plant <- function(plant, file = .plant_file) {
  saveRDS(plant, file)
}


# get growth info
get_stage <- function(points) {
  stage_idx <- max(which(growth_stages$min_points <= points))
  growth_stages(stage_idx, )
}


# get appropriate ASCII art plant
get_plant_art <- function(plant) {
  if (plant$health <= 0) {
    return(plant_art$dead)
  }
  if (plant$health < 30) {
    return(plant_art$wilted)
  }
  stage <- get_stage(plant$points)
  plant_art((stage$art_name))
}

days_since <- function(date) {
  as.integer(Sys.Date() - as.Date(date))
}


# Messages for encouragement - Done with help of chatGPT
get_encouragement <- function() {
  messages <- c(
    "Your plant appreciates you!",
    "Keep up the great work!",
    "You're a natural plant parent!",
    "Your R sessions make the plant happy!",
    "Photosynthesis in progress... ",
    "Growing strong, just like your R skills!",
    "The plant sends positive vibes!",
    "Another day, another leaf!",
    "Your dedication is blooming!",
    "Keep coding, keep growing!"
  )
  sample(messages, 1)
}


# General health
get_health_message <- function(health) {
  if (health >= 90) {
    return("Thriving! Your plant is radiantly healthy!")
  } else if (health >= 70) {
    return("Healthy! Looking good!")
  } else if (health >= 50) {
    return("Okay. Could use some attention.")
  } else if (health >= 30) {
    return("Struggling. Please water me!")
  } else if (health > 0) {
    return("Critical! Water immediately or I'll die!")
  } else {
    return("Your plant has died. Start a new one with PlantNew()")
  }
}


# ---- main functions

PlantNew <- function(name = NULL, file = .plant_file) {
  existing <- get_plant(file)
  
  if (!is.null(existing) && existing$health > 0) {
    cat("  You already have a plant named '", existing$name, "'!n", sep = "")
    cat(" Health: ", existing$health, "% | Stage: ", 
        get_stage(existing$points)$name, "nn", sep = "")
    cat("  Are you sure you want to replace it? (yes/no): ")
    response <- tolower(readline())
    if (response != "yes") {
      cat("  Keeping your existing plant.  nn")
    }
  }
  
  
  # Get plant name
  if (is.null(name)) {
    suggestions <- c("Fernie Bennes", "Morgan Treeman", "Leaf Seinfeld",
                     "Plantonio Banderas", "Elvis Parsley", "Kramerofern",
                     "Snake Costanza", "Aloe NewmanVera", "Jungle Tribbiani")
    
    cat("n")
    cat("    NEW PLANT!n")
    cat("  Some name suggestions:n")
    for (i in seq_along(suggestions)) {
      cat(sprintf("    %d. %sn", i, suggestions(i)))
    }
    cat("n  Enter a name (or number, or press Enter for random): ")
    input <- readline()
    
    if (input == "") {
      name <- sample(suggestions, 1)
    } else if (grepl("^(0-9)+$", input)) {
      idx <- as.integer(input)
      if (idx >= 1 && idx <= length(suggestions)) {
        name <- suggestions(idx)
      } else {
        name <- input
      }
    } else {
      name <- input
    }
  }
  
  # Create new plant
  plant <- list(
    name = name,
    species = "R-Plant (Programmus enthusiasticus)",
    planted_date = Sys.Date(),
    last_watered = Sys.Date(),
    last_visited = Sys.time(),
    points = 0,
    health = 100,
    times_watered = 0,
    sessions = 0,
    achievements = character(0)
  )
  
  save_plant(plant, file)

  cat("n")
  cat("  ╔", hline("═", 44), "╗n", sep = "")
  cat("  ║         NEW PLANT CREATED!               ║n")
  cat("  ╚", hline("═", 44), "╝n", sep = "")
  cat("n")
  
  art <- plant_art$seed
  for (line in art) {
    cat("        ", line, "n", sep = "")
  }
  
  cat("n")
  cat("Name:    ", name, "n", sep = "")
  cat("Species: ", plant$species, "n", sep = "")
  cat("Planted: ", format(Sys.Date(), "%B %d, %Y"), "n", sep = "")
  cat("n")
  cat("Tips:n")
  cat(" --> Use WaterPlant() to water your plantn")
  cat(" --> Use CheckPlant() to see its statusn")
  cat(" --> Visit often - your R sessions help it grow!n")
  cat("n")

}



# -- Water planting 
WaterPlant <- function(file = .plant_file) {
  plant <- get_plant(file)
  if (is.null(plant)) {
    cat("n No plant found! Start one with PlantNew()nn")
  }
  
  if (plant$health <= 0) {
    cat("n  Your plant has died. Start a new one with PlantNew()nn")
  }
  
  # Check if already watered today
  last_water_date <- as.Date(plant$last_watered)
  today <- Sys.Date()
  
  if (last_water_date == today) {
    cat("n")
    cat("  Already watered today!n")
    cat("  Your plant doesn't want to drown. n")
    cat("  Come back tomorrow!nn")
    return(invisible(plant))
  }
  
  # Calculate bonus for consecutive days
  days_since_water <- days_since(plant$last_watered)
  water_points <- 15
  health_gain <- 20
  if (days_since_water == 1) {
    water_points <- water_points + 5  # Consecutive day bonus
    plant$achievements <- union(plant$achievements, "daily_waterer")
  }
  
  plant$last_watered <- today
  plant$points <- plant$points + water_points
  plant$health <- min(100, plant$health + health_gain)
  plant$times_watered <- plant$times_watered + 1
  plant$last_visited <- Sys.time()
  
  # Check for achievements
  if (plant$times_watered == 10 && !"10_waters" %in% plant$achievements) {
    plant$achievements <- c(plant$achievements, "10_waters")
  }
  if (plant$times_watered == 50 && !"50_waters" %in% plant$achievements) {
    plant$achievements <- c(plant$achievements, "50_waters")
  }
  
  save_plant(plant, file)
  
  # Get stage info
  old_stage <- get_stage(plant$points - water_points)
  new_stage <- get_stage(plant$points)
  leveled_up <- new_stage$stage > old_stage$stage
  
  # Display
  cat("n")
  cat("  ╔", hline("═", 44), "╗n", sep = "")
  cat("  ║            WATERING TIME!                 ║n")
  cat("  ╚", hline("═", 44), "╝n", sep = "")
  cat("n")

  cat("    Watering '", plant$name, "'...nn", sep = "")
  art <- get_plant_art(plant)
  for (line in art) {
    cat("        ", line, "n", sep = "")
  }

  cat(sprintf("  +%d growth points! (Total: %d)n", water_points, plant$points))
  cat(sprintf("  Health: %d%% %sn", plant$health, strrep("█", plant$health %/% 10)))

  if (leveled_up) {
    cat("n")
    cat("  ╔", hline("═", 44), "╗n", sep = "")
    cat("     LEVEL UP! Your plant is now: ", new_stage$emoji, " ", new_stage$name, "n", sep = "")
    cat("  ╔", hline("═", 44), "╗n", sep = "")
  }
  cat("n  ", get_encouragement(), "nn", sep = "")
}


# --  Check on your desk plant
CheckPlant <- function(file = .plant_file) {
  plant <- get_plant(file)
  if (is.null(plant)) {
    cat("n    No plant found! Start one with PlantNew()nn")
  }
  
  days_without_water <- days_since(plant$last_watered)
  if (days_without_water > 1 && plant$health > 0) {
    # Lose health for each day without water (after first day)
    health_loss <- (days_without_water - 1) * 10
    plant$health <- max(0, plant$health - health_loss)
  }
  
  session_start <- Sys.getenv("R_SESSION_TMPDIR")  # Unique per session
  
  visit_points <- 2
  plant$points <- plant$points + visit_points
  plant$sessions <- plant$sessions + 1
  plant$last_visited <- Sys.time()

  if (plant$sessions == 100 && !"100_sessions" %in% plant$achievements) {
    plant$achievements <- c(plant$achievements, "100_sessions")
  }
  
  save_plant(plant, file)
  
  # Get stage info
  stage <- get_stage(plant$points)
  days_alive <- days_since(plant$planted_date)
  
  # Display
  cat("n")
  cat("  ╔", hline("═", 44), "╗n", sep = "")
  cat("  ║          PLANT STATUS REPORT              ║n")
  cat("  ╚", hline("═", 44), "╝n", sep = "")
  cat("n")
  
  # Show art
  art <- get_plant_art(plant)
  for (line in art) {
    cat("        ", line, "n", sep = "")
  }
  
  cat("n")
  cat("  ", hline("─", 44), "n", sep = "")
  cat(sprintf("  Name:        %sn", plant$name))
  cat(sprintf("  Age:         %d day%s oldn", days_alive, if(days_alive != 1) "s" else ""))
  cat(sprintf("  Stage:       %s %sn", stage$emoji, stage$name))
  cat(sprintf("  Points:      %d / %d (next stage)n", 
              plant$points, 
              ifelse(stage$stage < 7, growth_stages$min_points(stage$stage + 2), "MAX")))
  cat("  ", hline("─", 44), "n", sep = "")
  
  # Health bar
  health_bar <- paste0(
    strrep("█", plant$health %/% 10),
    strrep("░", 10 - plant$health %/% 10)
  )
  cat(sprintf("  Health:      (%s) %d%%n", health_bar, plant$health))
  cat(sprintf("  Status:      %sn", get_health_message(plant$health)))
  cat("  ", hline("─", 44), "n", sep = "")
  
  # Water status
  days_since_water <- days_since(plant$last_watered)
  if (days_since_water == 0) {
    water_status <- " Watered today!"
  } else if (days_since_water == 1) {
    water_status <- " Watered yesterday"
  } else {
    water_status <- sprintf("   %d days without water!", days_since_water)
  }
  cat(sprintf("  Last water:  %sn", water_status))
  cat("  ", hline("─", 44), "n", sep = "")

  # Stats
  cat(sprintf("  Waterings:   %d totaln", plant$times_watered))
  cat(sprintf("  Visits:      %d R sessionsn", plant$sessions))
  
  # Achievements
  if (length(plant$achievements) > 0) {
    cat("  ", hline("─", 44), "n", sep = "")
    cat("    Achievements:n")
    achievement_names <- list(
      "daily_waterer" = "Daily Waterer - Watered on consecutive days",
      "10_waters" = "Hydration Helper - Watered 10 times",
      "50_waters" = "Water Master - Watered 50 times",
      "100_sessions" = "Dedicated Parent - 100 R sessions"
    )
    for (ach in plant$achievements) {
      if (ach %in% names(achievement_names)) {
        cat(sprintf("  %sn", achievement_names((ach))))
      }
    }
  }
  
  if (days_since_water >= 1 && plant$health > 0) {
    cat("  Don't forget to WaterPlant()!nn")
  }
  
}


# Quick status - just show the plant
Plant <- function(file = .plant_file) {
  plant <- get_plant(file)
  
  if (is.null(plant)) {
    cat("n No plant! Use PlantNew() to start.nn")
  }
  
  # Update health decay silently
  days_without_water <- days_since(plant$last_watered)
  if (days_without_water > 1 && plant$health > 0) {
    health_loss <- (days_without_water - 1) * 10
    plant$health <- max(0, plant$health - health_loss)
    save_plant(plant, file)
  }
  
  stage <- get_stage(plant$points)
  art <- get_plant_art(plant)
  
  cat("n")
  for (line in art) {
    cat("        ", line, "n", sep = "")
  }
  cat("n")
  cat(sprintf("  %s %s | Day %d | %d%% healthn",
              stage$emoji, plant$name, 
              days_since(plant$planted_date),
              plant$health))
  cat("n")
}


PlantDelete <- function(file = .plant_file, confirm = TRUE) {
  
  plant <- get_plant(file)
  
  if (is.null(plant)) {
    cat("n  No plant to delete.nn")
    return(invisible(FALSE))
  }
  
  if (confirm) {
    cat("n  Are you sure you want to delete '", plant$name, "'?n", sep = "")
    cat("  This cannot be undone! (yes/no): ")
    response <- tolower(readline())
    if (response != "yes") {
      cat("  Keeping your plant safe.  nn")
    }
  }
  
  file.remove(file)
  cat("n Goodbye, ", plant$name, "...n", sep = "")
  cat(" Use PlantNew() to start fresh.nn")
}

#optional
.onAttach <- function() {
  plant <- get_plant()
  if (!is.null(plant) && plant$health > 0) {
    stage <- get_stage(plant$points)
    message(sprintf(" Your plant '%s' (%s) is waiting! Use CheckPlant() to visit.",
                    plant$name, stage$name))
  }
}

# Run welcome check
local({
  plant <- get_plant()
  if (!is.null(plant) && plant$health > 0) {
    days_without_water <- days_since(plant$last_watered)
    stage <- get_stage(plant$points)
    cat(sprintf("n '%s' says hello! (%s, Day %d)n",
                plant$name, stage$name, days_since(plant$planted_date)))
    if (days_without_water >= 2) {
      cat(sprintf("It's been %d days without water!n", days_without_water))
    }
    cat("n")
  }
})


Sfaturi PRO:

  • Apă zilnic pentru puncte bonus
  • Doar rularea CheckPlant() oferă puncte mici de creștere
  • Nu uitați să udați sau planta se va ofili!
  • Sănătate sub 30% = ofilit, Sănătate 0% = mort

Verificați depozitul pentru actualizări viitoare!

Rămâi sănătos și fericit cu codificarea R!

Disclaimer: toată arta ASCII a fost realizată de GPT, precum și numele plantelor și progresul jocului ASCII.

Dominic Botezariu
Dominic Botezariuhttps://www.noobz.ro/
Creator de site și redactor-șef.

Cele mai noi știri

Pe același subiect

LĂSAȚI UN MESAJ

Vă rugăm să introduceți comentariul dvs.!
Introduceți aici numele dvs.