feat: improve city selection for weather arts generation

- Introduce `get_recent_cities` to filter out cities that have been recently generated weather arts.
- Update `select_cities` method to exclude recent cities from the selection process, ensuring diversity in the generated arts.
- Modify the `select_countries` method to maintain its functionality while integrating recent city filtering.

This update enhances the system's ability to select active cities efficiently, reducing redundancy and improving the variety of generated weather arts by avoiding recent candidates.
This commit is contained in:
songtianlun 2025-02-17 12:58:16 +08:00
parent f1815afc41
commit 104597e3ba

View File

@ -15,7 +15,8 @@ class BatchGenerateWeatherArtsWorker
remaining_slots = [ remaining_slots, PER_RUN_GENERATION_LIMIT ].min remaining_slots = [ remaining_slots, PER_RUN_GENERATION_LIMIT ].min
countries_to_process = select_countries countries_to_process = select_countries
cities_to_process = select_cities(countries_to_process, remaining_slots)&.shuffle recent_cities = get_recent_cities
cities_to_process = select_cities(recent_cities, countries_to_process, remaining_slots)&.shuffle
print_cities_list(cities_to_process, start_time) print_cities_list(cities_to_process, start_time)
skipped_cities = [] skipped_cities = []
@ -39,6 +40,16 @@ class BatchGenerateWeatherArtsWorker
private private
def get_recent_cities
cutoff_time = Time.current - GENERATION_INTERVAL
City.joins("LEFT JOIN (
SELECT city_id, MAX(created_at) as last_generation_time
FROM weather_arts
GROUP BY city_id
) latest_arts ON cities.id = latest_arts.city_id")
.where("latest_arts.last_generation_time < ?", cutoff_time)
end
def calculate_remaining_slots def calculate_remaining_slots
today_generations = WeatherArt today_generations = WeatherArt
.where("DATE(created_at) = ?", Date.today) .where("DATE(created_at) = ?", Date.today)
@ -50,9 +61,6 @@ class BatchGenerateWeatherArtsWorker
end end
def select_countries def select_countries
cutoff_time = Time.current - GENERATION_INTERVAL
Country.all.select do |country| Country.all.select do |country|
timezone_info = country.timezones.present? ? JSON.parse(country.timezones).first : { "zoneName" => "UTC" } timezone_info = country.timezones.present? ? JSON.parse(country.timezones).first : { "zoneName" => "UTC" }
local_time = Time.current.in_time_zone(ActiveSupport::TimeZone[timezone_info["zoneName"]]) local_time = Time.current.in_time_zone(ActiveSupport::TimeZone[timezone_info["zoneName"]])
@ -60,10 +68,12 @@ class BatchGenerateWeatherArtsWorker
end end
end end
def select_cities(countries, limit) def select_cities(recent_city, countries, limit)
cutoff_time = Time.current - GENERATION_INTERVAL
Rails.logger.debug "Select Cities with limit: #{limit}, in #{countries.size} countries." Rails.logger.debug "Select Cities with limit: #{limit}, in #{countries.size} countries."
# 第一阶段:筛选 active 城市 # 第一阶段:筛选 active 城市, 排除最近生成过的城市
active_cities = City.where(active: true, country_id: countries.map(&:id)).limit(limit).to_a active_cities = City.where.not(id: recent_city.pluck(:id))
.where(active: true, country_id: countries.map(&:id)).limit(limit).to_a
selected = active_cities.first(limit) selected = active_cities.first(limit)
remaining = limit - selected.size remaining = limit - selected.size
Rails.logger.debug "Step1: Selected #{selected.size} cities with active city." Rails.logger.debug "Step1: Selected #{selected.size} cities with active city."
@ -79,17 +89,17 @@ class BatchGenerateWeatherArtsWorker
Rails.logger.debug "Step2: Selected #{remaining_every_country_count} cities in every country" Rails.logger.debug "Step2: Selected #{remaining_every_country_count} cities in every country"
select_countries.each do |country| select_countries.each do |country|
c = City.where.not(id: select_countries.pluck(:id)) c = City.where.not(id: recent_city.pluck(:id))
.where(country_id: country.id) .where.not(id: select_countries.pluck(:id))
.order(Arel.sql("RANDOM()")) .where(country_id: country.id)
.first(remaining_every_country_count) .order(Arel.sql("RANDOM()"))
.first(remaining_every_country_count)
if c.any? # 检查是否有有效的城市 if c.any? # 检查是否有有效的城市
Rails.logger.debug "== Selected city [#{c.first.name}] in country: [#{country.name}]" Rails.logger.debug "== Selected city [#{c.first.name}] in country: [#{country.name}]"
selected << c selected << c
else else
Rails.logger.debug "== No valid cities found in country: [#{country.name}]" Rails.logger.debug "== No valid cities found in country: [#{country.name}]"
end end
selected << c
end end
Rails.logger.debug "Finished selected #{selected.size} cities." Rails.logger.debug "Finished selected #{selected.size} cities."
selected selected