refactor(OspfToolsPage): rename and restructure optimal cost hints to probability map for improved clarity and functionality
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m59s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m59s
This commit is contained in:
@@ -76,7 +76,7 @@ function buildOspfTemplatesFromRouterResults(routerResults = [], servers = []) {
|
|||||||
return Array.from(byComposite.values());
|
return Array.from(byComposite.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildOptimalCostHints(routeOptimizerData, servers = []) {
|
function buildOptimizerProbabilityMap(routeOptimizerData, servers = []) {
|
||||||
const homes = Array.isArray(routeOptimizerData?.homes) ? routeOptimizerData.homes : [];
|
const homes = Array.isArray(routeOptimizerData?.homes) ? routeOptimizerData.homes : [];
|
||||||
const byRef = new Map();
|
const byRef = new Map();
|
||||||
(servers || []).forEach((server) => {
|
(servers || []).forEach((server) => {
|
||||||
@@ -85,7 +85,7 @@ function buildOptimalCostHints(routeOptimizerData, servers = []) {
|
|||||||
.forEach((ref) => byRef.set(String(ref), server));
|
.forEach((ref) => byRef.set(String(ref), server));
|
||||||
});
|
});
|
||||||
|
|
||||||
const hints = {};
|
const probabilities = {};
|
||||||
|
|
||||||
homes.forEach((entry) => {
|
homes.forEach((entry) => {
|
||||||
const homeRefCandidates = [
|
const homeRefCandidates = [
|
||||||
@@ -119,18 +119,15 @@ function buildOptimalCostHints(routeOptimizerData, servers = []) {
|
|||||||
uniqueIface.forEach((candidate, idx) => {
|
uniqueIface.forEach((candidate, idx) => {
|
||||||
const iface = String(candidate?.interfaceName || '').trim();
|
const iface = String(candidate?.interfaceName || '').trim();
|
||||||
const hintKey = `${identity.key}::${iface.toUpperCase()}`;
|
const hintKey = `${identity.key}::${iface.toUpperCase()}`;
|
||||||
const nextHint = {
|
const probabilityOptimal = Number(candidate?.probabilityOptimal || 0);
|
||||||
optimalCost: (idx + 1) * OSPF_COST_STEP,
|
const prev = probabilities[hintKey];
|
||||||
probabilityOptimal: Number(candidate?.probabilityOptimal || 0),
|
if (prev == null || probabilityOptimal > prev) {
|
||||||
};
|
probabilities[hintKey] = probabilityOptimal;
|
||||||
const prev = hints[hintKey];
|
|
||||||
if (!prev || nextHint.probabilityOptimal > prev.probabilityOptimal) {
|
|
||||||
hints[hintKey] = nextHint;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return hints;
|
return probabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function OspfToolsPage() {
|
export default function OspfToolsPage() {
|
||||||
@@ -141,7 +138,7 @@ export default function OspfToolsPage() {
|
|||||||
const [optimizerLoading, setOptimizerLoading] = useState(false);
|
const [optimizerLoading, setOptimizerLoading] = useState(false);
|
||||||
const [saving, setSaving] = useState(false);
|
const [saving, setSaving] = useState(false);
|
||||||
const [dragging, setDragging] = useState(null);
|
const [dragging, setDragging] = useState(null);
|
||||||
const [optimalHints, setOptimalHints] = useState({});
|
const [optimizerProbabilities, setOptimizerProbabilities] = useState({});
|
||||||
|
|
||||||
const groupedByRouter = useMemo(() => {
|
const groupedByRouter = useMemo(() => {
|
||||||
const grouped = {};
|
const grouped = {};
|
||||||
@@ -171,6 +168,34 @@ export default function OspfToolsPage() {
|
|||||||
.sort((a, b) => a.area.localeCompare(b.area)),
|
.sort((a, b) => a.area.localeCompare(b.area)),
|
||||||
}));
|
}));
|
||||||
}, [templates, servers]);
|
}, [templates, servers]);
|
||||||
|
const optimalHints = useMemo(() => {
|
||||||
|
const hints = {};
|
||||||
|
|
||||||
|
groupedByRouter.forEach((routerGroup) => {
|
||||||
|
(routerGroup.areas || []).forEach((areaGroup) => {
|
||||||
|
const ranked = [...(areaGroup.items || [])]
|
||||||
|
.map((item) => {
|
||||||
|
const ifaceKey = `${routerGroup.routerKey}::${String(item.interfaceName || '').toUpperCase()}`;
|
||||||
|
const probabilityOptimal = Number(optimizerProbabilities[ifaceKey] || 0);
|
||||||
|
return { item, probabilityOptimal };
|
||||||
|
})
|
||||||
|
.sort((a, b) =>
|
||||||
|
Number(b.probabilityOptimal || 0) - Number(a.probabilityOptimal || 0) ||
|
||||||
|
String(a.item.interfaceName || '').localeCompare(String(b.item.interfaceName || ''))
|
||||||
|
);
|
||||||
|
|
||||||
|
ranked.forEach(({ item, probabilityOptimal }, idx) => {
|
||||||
|
const hintKey = `${routerGroup.routerKey}::${areaGroup.area}::${String(item.interfaceName || '').toUpperCase()}`;
|
||||||
|
hints[hintKey] = {
|
||||||
|
optimalCost: (idx + 1) * OSPF_COST_STEP,
|
||||||
|
probabilityOptimal,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return hints;
|
||||||
|
}, [groupedByRouter, optimizerProbabilities]);
|
||||||
const routerColumnClass = groupedByRouter.length > 1 ? 'col-12 col-xxl-6' : 'col-12';
|
const routerColumnClass = groupedByRouter.length > 1 ? 'col-12 col-xxl-6' : 'col-12';
|
||||||
|
|
||||||
const loadServers = async () => {
|
const loadServers = async () => {
|
||||||
@@ -208,11 +233,11 @@ export default function OspfToolsPage() {
|
|||||||
setOptimizerLoading(true);
|
setOptimizerLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await api.get('/route-optimizer', { timeout: 30000 });
|
const response = await api.get('/route-optimizer', { timeout: 30000 });
|
||||||
const hints = buildOptimalCostHints(response?.data, servers);
|
const probabilities = buildOptimizerProbabilityMap(response?.data, servers);
|
||||||
setOptimalHints(hints);
|
setOptimizerProbabilities(probabilities);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load route optimizer hints:', error);
|
console.error('Failed to load route optimizer hints:', error);
|
||||||
setOptimalHints({});
|
setOptimizerProbabilities({});
|
||||||
if (!silent) notify.warning('Не удалось загрузить рекомендации из оптимизатора маршрутов');
|
if (!silent) notify.warning('Не удалось загрузить рекомендации из оптимизатора маршрутов');
|
||||||
} finally {
|
} finally {
|
||||||
setOptimizerLoading(false);
|
setOptimizerLoading(false);
|
||||||
@@ -346,7 +371,7 @@ export default function OspfToolsPage() {
|
|||||||
<div className="list-group list-group-flush">
|
<div className="list-group list-group-flush">
|
||||||
{areaGroup.items.map((item) => (
|
{areaGroup.items.map((item) => (
|
||||||
(() => {
|
(() => {
|
||||||
const hint = optimalHints[`${routerGroup.routerKey}::${String(item.interfaceName || '').toUpperCase()}`];
|
const hint = optimalHints[`${routerGroup.routerKey}::${areaGroup.area}::${String(item.interfaceName || '').toUpperCase()}`];
|
||||||
const hintMatches = hint && Number(hint.optimalCost) === Number(item.cost);
|
const hintMatches = hint && Number(hint.optimalCost) === Number(item.cost);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
Reference in New Issue
Block a user