/
GeekNerd
/
ServerModelingProject
Обзор
Документация
Войти
/
GeekNerd
/
ServerModelingProject
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
Assets/Scripts/OptimizationLogic/Core/GreedyPlacer.cs
152 строки
6 KB
Gorney-Alex
Init
30 май 2026, 19:05
30 май 2026, 19:05
3cdcc49
Код
Авторство
О чём код?
using System; using System.Collections.Generic; using DataClasses; using DataClasses.Algorithm; using UnityEngine; namespace OptimizationLogic.Core { public sealed class GreedyPlacer { private static readonly float[] Rotations = { 0f, 90f, 180f, 270f }; public Chromosome Place(RoomConfig room, IReadOnlyList<PlacementZone> zones, IReadOnlyList<RackData> catalog) { Chromosome chromosome = new Chromosome(); if (room == null || zones == null || catalog == null) return chromosome; // Expand catalog into N genes (one per rack) List<(int modelIndex, float heat)> items = new(); for (int m = 0; m < catalog.Count; m++) { RackData model = catalog[m]; if (model == null) continue; int count = Mathf.Max(0, model.Quantity); for (int i = 0; i < count; i++) items.Add((m, Mathf.Max(0f, model.HeatOutput))); } // Sort by descending heat output items.Sort((a, b) => b.heat.CompareTo(a.heat)); PlacementValidator validator = new PlacementValidator(); List<RackGene> placed = new(); // Track current heat per zone for balancing Dictionary<int, float> zoneHeat = new(); for (int z = 0; z < zones.Count; z++) zoneHeat[zones[z].ZoneId] = 0f; for (int idx = 0; idx < items.Count; idx++) { int modelIndex = items[idx].modelIndex; RackGene best = new RackGene { ModelIndex = modelIndex, IsPlaced = false, Rotation = 0f, PositionX = 0f, PositionZ = 0f, ZoneId = -1 }; // Zone order: lowest current heat first List<PlacementZone> orderedZones = new List<PlacementZone>(zones); orderedZones.Sort((a, b) => zoneHeat[a.ZoneId].CompareTo(zoneHeat[b.ZoneId])); bool placedThis = false; for (int z = 0; z < orderedZones.Count && !placedThis; z++) { PlacementZone zone = orderedZones[z]; Vector2 coldDir = zone.ColdAirDirection; float[] sortedRotations = SortRotationsByColdDir(Rotations, coldDir); // Fallback for the whole zone, used only if no position in the zone allows dot < 0. RackGene zoneWideFallback = new RackGene { IsPlaced = false }; for (int p = 0; p < zone.CandidatePositions.Count && !placedThis; p++) { Vector2 pos = zone.CandidatePositions[p]; for (int r = 0; r < sortedRotations.Length; r++) { float rot = sortedRotations[r]; RackGene candidate = new RackGene { ModelIndex = modelIndex, IsPlaced = true, Rotation = rot, PositionX = pos.x, PositionZ = pos.y, ZoneId = zone.ZoneId }; if (!validator.IsPlacementValid(room, placed, candidate, catalog)) continue; float dot = Vector2.Dot(Geometry2D.FrontVectorFromRotation(rot), coldDir); // Accept any negative dot: front faces against the cold flow. if (dot < 0f) { best = candidate; placedThis = true; break; } // Neutral/bad orientation: store first valid as zone-wide fallback. if (!zoneWideFallback.IsPlaced) zoneWideFallback = candidate; // Rotations are sorted by dot ascending; if the best valid is already >= 0, // later rotations can't improve topology at this position. break; } } // If we never found dot < 0 anywhere in the zone, use the zone-wide fallback. if (!placedThis && zoneWideFallback.IsPlaced) { best = zoneWideFallback; placedThis = true; } } chromosome.Genes.Add(best); if (best.IsPlaced) { placed.Add(best); chromosome.PlacedCount++; zoneHeat[best.ZoneId] += Mathf.Max(0f, catalog[best.ModelIndex].HeatOutput); } } Debug.Log($"[GreedyPlacer] total={items.Count}, placed={chromosome.PlacedCount}"); for (int i = 0; i < chromosome.Genes.Count; i++) { RackGene g = chromosome.Genes[i]; if (g.IsPlaced) Debug.Log($" Gene[{i}] pos=({g.PositionX:F2},{g.PositionZ:F2}) rot={g.Rotation} zone={g.ZoneId}"); } return chromosome; } private static float[] SortRotationsByColdDir(float[] rotations, Vector2 coldDir) { float[] sorted = (float[])rotations.Clone(); Array.Sort(sorted, (a, b) => { float dotA = Vector2.Dot(Geometry2D.FrontVectorFromRotation(a), coldDir); float dotB = Vector2.Dot(Geometry2D.FrontVectorFromRotation(b), coldDir); return dotA.CompareTo(dotB); // ascending: -1 first }); return sorted; } } }