桌面整理规划程序,按使用频率摆放物品,提高找东西速度,工作更专注。

 

 

🖥️ 智能桌面整理规划系统 (Smart Desk Organizer)

 

一、实际应用场景描述

 

场景设定:深夜加班的“寻物迷宫”

 

凌晨1点,全栈工程师阿强正在赶一个紧急需求。

 

1. 打断时刻:他需要插入U盘拷贝文件,但在杂乱的桌面上摸索了整整2分钟。U盘被压在一堆线缆和便利贴下面。

2. 视觉噪音:抬头看到满屏的杂物,他的注意力从代码逻辑中被强行拉出,花了3分钟才重新进入心流状态。

3. 动线冗余:想喝口水,水杯却在显示器后面,他不得不转身、伸长手臂,甚至挪开键盘。

4. 次日循环:第二天早上,他试图整理桌面,但因为不知道什么东西该放哪,最后只是把东西从左边推到右边,毫无章法。

 

系统目标:通过算法分析阿强的使用习惯,将三维空间转化为二维坐标,生成一张“作战地图”,让高频物品触手可及,低频物品隐形收纳,重塑专注力。

 

二、引入痛点

 

痛点分类 具体表现 量化影响

时间黑洞 每天花费15‑30分钟寻找物品 每月损失约10小时有效工作时间

专注力破碎 平均每20分钟因寻找物品/整理而分心 心流状态难以维持超过1小时

空间熵增 物品随意堆放,可用面积<30% 心理压迫感强,效率递减

动线冗长 取水、拿笔等高频动作平均移动距离>50 cm 累计每日行走距离相当于半个马拉松

健康隐患 显示器过高/过低,座椅不适 颈椎、腰椎长期处于亚健康状态

 

三、核心逻辑讲解

 

1. 决策引擎架构

 

输入层 → 分析层 → 优化层 → 输出层

 ├─ 工作类型 ├─ 频率分析 ├─ 贪心算法 ├─ SVG布局图

 ├─ 设备配置 ├─ 时间模式 ├─ 热区填充 ├─ 实施清单

 └─ 桌面尺寸 └─ 关联规则 └─ AABB碰撞 └─ 动线报告

 

2. 核心算法详解

 

① 使用频率评分模型 (Weighted Scoring Model)

 

# 综合频率得分 = 基础频率 × 0.4 + 人体工学权重 × 0.3 + 固定性 × 0.2 + 电源需求 × 0.1

# 目的:区分“一直用”(如显示器)和“经常用”(如签字笔)的优先级

 

② 空间优化:贪心算法 (Greedy Algorithm)

 

# 伪代码

Sort items by priority DESC

For each item in items:

    Find the first free spot in its preferred zone

    If spot found:

        Place item

    Else:

        Place item in overflow area (边缘区)

 

逻辑:优先保证最重要的物品占据最佳位置。

 

③ 碰撞检测:AABB (Axis-Aligned Bounding Box)

 

# 判断两个矩形是否重叠

if (rect1.x < rect2.x + rect2.width &&

    rect1.x + rect1.width > rect2.x &&

    rect1.y < rect2.y + rect2.height &&

    rect1.y + rect1.height > rect2.y):

       return COLLISION

 

逻辑:确保物品在桌面上不相互重叠。

 

四、代码模块化实现

 

📁 

"README.md"

 

# 智能桌面整理规划系统 (Smart Desk Organizer)

 

## 🚀 项目简介

基于智能决策算法与人体工学,为您杂乱的桌面生成科学、高效的物品摆放坐标方案。

 

## ✨ 核心功能

- 📊 使用频率智能分析 (程序员/设计师/学生)

- 🧠 空间热区优先占位算法

- 📐 可视化 SVG 布局图生成

- ⏱️ 动线距离与寻物时间预估

- 📋 一键生成实施清单 (Checklist)

 

## 🛠️ 技术栈

- Python 3.8+

- 贪心算法 (Greedy Algorithm)

- AABB 碰撞检测

- SVG / HTML 可视化

 

## 📦 安装与使用

 

bash

 

pip install -r requirements.txt

 

python main.py

 

 

## 📂 项目结构

 

desktop_organizer/

 

├── main.py # 程序入口

 

├── config/

 

│ └── items_database.py # 物品属性数据库

 

├── core/

 

│ ├── frequency_analyzer.py # 频率分析引擎

 

│ ├── space_optimizer.py # 空间优化引擎

 

│ └── layout_generator.py # 布局渲染器

 

├── utils/

 

│ └── helpers.py # 工具类 (验证/日志)

 

└── output/ # 生成的报告目录

 

📄 

"main.py" (程序入口)

 

"""

智能桌面整理规划系统 - 主控制器

====================================

严格按照:场景 -> 痛点 -> 决策 -> 输出的逻辑流

"""

 

import sys

from pathlib import Path

from typing import Dict

 

# 动态添加项目路径

sys.path.append(str(Path(__file__).parent))

 

from core.frequency_analyzer import FrequencyAnalyzer

from core.space_optimizer import SpaceOptimizer

from core.layout_generator import LayoutGenerator

from utils.helpers import InputValidator, Logger, ConsoleUI

 

 

class DesktopOrganizerApp:

    """

    应用场景: 解决用户因桌面杂乱导致的效率低下问题

    核心逻辑: 输入环境参数 -> 分析频率 -> 计算坐标 -> 输出可视化方案

    """

 

    def __init__(self):

        self.ui = ConsoleUI()

        self.validator = InputValidator()

        self.logger = Logger("MainApp")

 

    def run(self):

        self.ui.print_welcome()

        try:

            # 1. 收集环境数据 (痛点输入)

            env_data = self._collect_environment_data()

 

            # 2. 频率分析 (决策层)

            self.ui.print_step("正在分析您的使用习惯与物品频率...")

            analyzer = FrequencyAnalyzer()

            frequency_report = analyzer.analyze(env_data['work_type'])

 

            # 3. 空间优化 (核心算法)

            self.ui.print_step("正在计算黄金三角区与最优坐标 (贪心算法)...")

            optimizer = SpaceOptimizer()

            layout_plan = optimizer.optimize(

                frequency_report,

                env_data['desk_dimensions'],

                env_data['device_type']

            )

 

            # 4. 生成输出 (结果呈现)

            self.ui.print_step("正在渲染可视化布局图...")

            generator = LayoutGenerator()

            report_path = generator.generate(layout_plan, env_data, frequency_report)

 

            # 5. 展示结果

            self.ui.print_results(report_path, layout_plan)

 

        except KeyboardInterrupt:

            self.ui.print_exit()

        except Exception as e:

            self.logger.error(f"系统崩溃: {e}", exc_info=True)

            self.ui.print_error(str(e))

 

    def _collect_environment_data(self) -> Dict:

        """收集并验证用户输入 (引入痛点环节)"""

        self.ui.print_prompt("让我们开始定制您的专属桌面方案:")

 

        work_type = self.ui.get_input(

            "请输入工作类型 (程序员/设计师/学生): ",

            validator=self.validator.validate_work_type

        )

        device_type = self.ui.get_input(

            "请输入设备类型 (笔记本/双屏/单屏): ",

            validator=self.validator.validate_device_type

        )

        desk_dims = self.ui.get_input(

            "请输入桌面尺寸 (长x宽 cm, 例: 120x60): ",

            validator=self.validator.validate_dimensions

        )

 

        width, depth = map(int, desk_dims.split('x'))

        return {

            "work_type": work_type,

            "device_type": device_type,

            "desk_dimensions": (width, depth)

        }

 

 

if __name__ == "__main__":

    app = DesktopOrganizerApp()

    app.run()

 

📄 

"core/frequency_analyzer.py"

 

"""

使用频率分析模块

================

核心逻辑:基于职业画像,计算物品的“隐形”使用频率

"""

 

from typing import Dict, List

from dataclasses import dataclass

from config.items_database import ITEMS_DATABASE, WORK_TYPE_MODIFIERS

 

 

@dataclass

class FrequencyReport:

    """频率分析报告数据类"""

    items: Dict[str, float] # {item_name: score}

    work_type: str

 

 

class FrequencyAnalyzer:

    """

    痛点解决:用户往往凭感觉整理,而不是凭数据。

    该模块将“感觉”量化为“分数”。

    """

 

    def analyze(self, work_type: str) -> FrequencyReport:

        """

        核心逻辑讲解:

        1. 获取职业基础配置 (如程序员高频用键盘,设计师高频用手绘板)

        2. 叠加人体工学权重 (固定物品如显示器权重更高)

        3. 计算综合得分

        """

        scores = {}

        modifier = WORK_TYPE_MODIFIERS.get(work_type, {})

 

        for name, item in ITEMS_DATABASE.items():

            # 基础分 + 职业修正分

            base_score = item.base_frequency

            profession_bonus = modifier.get(item.category, 1.0)

 

            # 最终得分,范围 0-10

            final_score = min(10, base_score * profession_bonus * item.ergonomic_weight)

            scores[name] = round(final_score, 2)

 

        # 按分数降序排序,为贪心算法做准备

        return FrequencyReport(

            items=dict(sorted(scores.items(), key=lambda x: x[1], reverse=True)),

            work_type=work_type

        )

 

📄 

"core/space_optimizer.py"

 

"""

空间优化引擎

================

核心逻辑:使用贪心算法将高频物品填入黄金三角区

"""

 

from typing import Dict, Tuple, List

import math

from dataclasses import dataclass

 

from config.items_database import ITEMS_DATABASE

 

 

@dataclass

class ItemPlacement:

    """物品最终摆放位置"""

    name: str

    x: int

    y: int

    width: int

    height: int

    priority: float

 

 

class SpaceOptimizer:

    """

    痛点解决:物品乱放导致动线过长。

    核心算法:贪心算法 + AABB 碰撞检测。

    """

 

    # 人体工学黄金三角区定义 (以桌面左下角为原点)

    GOLDEN_TRIANGLE = {'x_min': 30, 'x_max': 80, 'y_min': 10, 'y_max': 40}

 

    def optimize(

        self,

        frequency_report: object,

        desk_dimensions: Tuple[int, int],

        device_type: str

    ) -> Dict:

        """

        执行空间优化

        """

        placements: List[ItemPlacement] = []

        occupied_rects = [] # 已占用的矩形区域,用于碰撞检测

 

        # 按优先级从高到低处理物品 (贪心策略)

        for item_name, priority in frequency_report.items.items():

            item = ITEMS_DATABASE[item_name]

            placed = False

 

            # 尝试放入黄金三角区

            if priority > 3.0: # 高频物品

                target_area = self.GOLDEN_TRIANGLE

            else: # 低频物品

                target_area = {'x_min': 0, 'x_max': desk_dimensions[0],

                               'y_min': 40, 'y_max': desk_dimensions[1]}

 

            # 扫描目标区域寻找空位 (AABB检测)

            pos = self._find_free_spot(item, target_area, occupied_rects)

 

            if pos:

                px, py = pos

                placements.append(ItemPlacement(item_name, px, py, item.width, item.height, priority))

                occupied_rects.append({'x': px, 'y': py, 'w': item.width, 'h': item.height})

                placed = True

 

            # 如果没放下,放到边缘溢出区

            if not placed:

                overflow_pos = self._place_in_overflow(item, desk_dimensions, occupied_rects)

                px, py = overflow_pos

                placements.append(ItemPlacement(item_name, px, py, item.width, item.height, priority))

                occupied_rects.append({'x': px, 'y': py, 'w': item.width, 'h': item.height})

 

        return {

            "placements": placements,

            "desk_dimensions": desk_dimensions,

            "metrics": self._calculate_metrics(placements, frequency_report)

        }

 

    def _find_free_spot(self, item, area: Dict, occupied: List[Dict]) -> Tuple[int, int] | None:

        """扫描区域寻找第一个不重叠的位置"""

        step = 5 # 5cm 网格

        for y in range(area['y_min'], area['y_max'] - item.height, step):

            for x in range(area['x_min'], area['x_max'] - item.width, step):

                if not self._is_colliding(x, y, item.width, item.height, occupied):

                    return x, y

        return None

 

    def _is_colliding(self, x, y, w, h, occupied):

        """AABB 碰撞检测核心逻辑"""

        for rect in occupied:

            if (x < rect['x'] + rect['w'] and x + w > rect['x'] and

                y < rect['y'] + rect['h'] and y + h > rect['y']):

                return True

        return False

 

    def _place_in_overflow(self, item, desk_dims, occupied):

        """放置到右下角溢出区"""

        x = desk_dims[0] - item.width - 5

        y = desk_dims[1] - item.height - 5

        # 确保不重叠

        while self._is_colliding(x, y, item.width, item.height, occupied):

            y -= 5

        return x, y

 

    def _calculate_metrics(self, placements, report):

        """计算优化前后的动线指标"""

        avg_distance = sum(math.sqrt(p.x**2 + p.y**2) for p in placements) / len(placements)

        high_freq_in_golden = sum(1 for p in placements if p.priority > 3.0 and

                                   self.GOLDEN_TRIANGLE['x_min'] <= p.x <= self.GOLDEN_TRIANGLE['x_max'])

        return {

            "average_reach_distance_cm": round(avg_distance, 2),

            "high_freq_accessibility": f"{high_freq_in_golden / max(1, len(placements)) * 100:.1f}%"

        }

 

📄 

"core/layout_generator.py"

 

"""

布局生成器

================

将坐标数据转化为可视化的 SVG 和 HTML 报告

"""

 

from typing import Dict

import os

from datetime import datetime

 

 

class LayoutGenerator:

    """

    痛点解决:用户看不懂坐标数据。

    核心逻辑:将抽象的(x, y)转化为直观的图形。

    """

 

    def generate(self, layout_plan: Dict, env_data: Dict, freq_report: Dict) -> str:

        """生成 HTML/SVG 报告"""

        output_dir = "output"

        os.makedirs(output_dir, exist_ok=True)

 

        html_path = os.path.join(output_dir, f"desk_layout_{datetime.now().strftime('%Y%m%d')}.html")

 

        svg_content = self._render_svg(layout_plan)

 

        with open(html_path, 'w', encoding='utf-8') as f:

            f.write(f"""

            <!DOCTYPE html>

            <html><head><title>桌面布局方案</title>

            <style>

                body {{ font-family: sans-serif; background: #f0f2f5; }}

                .container {{ max-width: 900px; margin: auto; background: white; padding: 20px; border-radius: 8px; }}

                svg {{ border: 1px solid #ccc; background: #fff; }}

                .item {{ fill: #3498db; stroke: #2c3e50; stroke-width: 1; }}

                .golden-area {{ fill: rgba(255, 215, 0, 0.2); stroke: #f1c40f; stroke-dasharray: 5,5; }}

            </style></head>

            <body>

                <div class="container">

                    <h1>🖥️ {env_data['work_type']} 桌面优化方案</h1>

                    <p>设备: {env_data['device_type']} | 尺寸: {layout_plan['desk_dimensions'][0]}x{layout_plan['desk_dimensions'][1]} cm</p>

                    {svg_content}

                    <h3>实施清单</h3>

                    <ul>

                        {"".join(f"<li><b>{p.name}</b>: 放置于 ({p.x}, {p.y})</li>" for p in layout_plan['placements'])}

                    </ul>

                </div>

            </body></html>

            """)

 

        return html_path

 

    def _render_svg(self, layout_plan: Dict) -> str:

        """渲染 SVG 图形"""

        w, h = layout_plan['desk_dimensions']

        scale = 4 # 1cm = 4px

 

        svg_items = []

        # 绘制黄金三角区背景

        gt = SpaceOptimizer.GOLDEN_TRIANGLE

        svg_items.append(

            f'<rect x="{gt["x_min"]*scale}" y="{gt["y_min"]*scale}" '

            f'width="{(gt["x_max"]-gt["x_min"])*scale}" height="{(gt["y_max"]-gt["y_min"])*scale}" '

            f'class="golden-area"/>'

        )

 

        # 绘制物品

        for p in layout_plan['placements']:

            color = "#e74c3c" if p.priority > 3 else "#3498db"

            svg_items.append(

                f'<rect x="{p.x*scale}" y="{p.y*scale}" '

                f'width="{p.width*scale}" height="{p.height*scale}" '

                f'class="item" fill="{color}" />'

                f'<text x="{(p.x + p.width/2)*scale}" y="{(p.y + p.height/2)*scale}" '

                f'text-anchor="middle" fill="white" font-size="10">{p.name[:2]}</text>'

            )

 

        return f'<svg width="{w*scale + 20}" height="{h*scale + 20}">{"".join(svg_items)}</svg>'

 

五、核心知识点卡片

 

📇 卡片 1:贪心算法 (Greedy Algorithm)

 

# 🎯 知识点:贪心算法 (Greedy Algorithm)

 

## 是什么?

一种在每一步选择中都采取当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法。

 

## 在桌面整理中的应用

1. **排序**:将所有物品按“使用频率”从高到低排序。

2. **占位**:取出频率最高的物品,在它的“首选区域”(如黄金三角区)寻找第一个可用的空位。

3. **重复**:处理下一个物品,直到所有物品都有位置。

 

## 为什么用它?

* **效率高**:时间复杂度接近 O(N log N)(主要是排序),非常适合快速生成布局。

* **实现简单**:不需要复杂的回溯或穷举搜索。

* **效果可接受**:对于桌面整理这种非精确求解问题,“局部最优”通常能带来“足够好”的全局效果。

 

## 局限性与对策

* **局限性**:可能会因为先放置了一个大家具,导致后面无法放置更合适的物品。

* **对策**:在实际应用中,可以结合“装箱问题”的启发式规则(如 Best Fit Decreasing)进行微调。

 

📇 卡片 2:AABB 碰撞检测 (Axis-Aligned Bounding Box)

 

# 🎯 知识点:AABB 碰撞检测

 

## 是什么?

判断两个轴对齐的矩形(物品)是否在平面上重叠的最快算法。

 

## 数学原理

对于矩形 A (x1, y1, w1, h1) 和矩形 B (x2, y2, w2, h2):

 

发生碰撞的充分必要条件:

 

(A的左边界 < B的右边界) 且

 

(A的右边界 > B的左边界) 且

 

(A的上边界 < B的下边界) 且

 

(A的下边界 > B的上边界)

 

 

## 代码实现 (核心逻辑)

 

python

 

def is_colliding(ax, ay, aw, ah, bx, by, bw, bh):

 

return (ax < bx + bw and ax + aw > bx and

 

ay < by + bh and ay + ah > by)

 

 

## 为什么它重要?

它是 `SpaceOptimizer` 的基石。如果没有碰撞检测,物品就会像幽灵一样重叠在一起,布局将失去物理意义。

 

📇 卡片 3:人体工学黄金三角区 (Ergonomic Golden Triangle)

 

# 🎯 知识点:人体工学黄金三角区

 

## 定义

指人在标准坐姿下,视线自然俯视 15‑30 度,且双臂自然弯曲放置在桌面上时,手肘能够轻松覆盖的一个近似三角形的区域。

 

## 坐标模型 (简化版)

* **X 轴 (深度)**: 距离身体 30‑80 cm

* **Y 轴 (左右)**: 距离桌面中心线 ±20 cm

 

## 核心价值

* **零思考区**:将“一直要用”的东西(键盘、鼠标、常用笔)放在这里,实现“肌肉记忆”级别的取用。

* **效率最大化**:在这个区域内取物,手臂移动距离最短,几乎不需要转头或起身。

* **健康保障**:保持颈椎正直,手腕处于自然中立位,预防职业病。

 

## 在本项目中的体现

 

python

 

高频物品 (priority > 3.0) 会被算法强制优先放入此区域

 

if priority > 3.0:

 

target_area = self.GOLDEN_TRIANGLE

 

六、总结

 

🎯 项目回顾

 

本次实战严格遵循了“实际应用场景 → 引入痛点 → 核心逻辑讲解 → 代码模块化 → 知识卡片 → 总结”的技术布道路径。

 

我们不仅编写了一个工具,更是构建了一套空间决策系统:

 

1. 场景具象化:通过深夜加班的具体情境,引出桌面杂乱这一普遍痛点。

2. 算法驱动:摒弃了“凭感觉整理”,引入了贪心算法进行排序占位,利用AABB进行物理碰撞检测,结合人体工学划定热区。

3. 工程化思维:代码严格模块化,

"main.py" 负责流程控制,

"core" 目录下的模块各司其职,符合高内聚低耦合的设计原则。

 

💡 核心感悟

 

作为全栈工程师,我们常习惯于解决逻辑严密的功能需求。智能决策的魅力在于,它能将模糊的“生活习惯”转化为精确的“数学坐标”。这套系统的价值不在于代码量,而在于它背后的决策模型——让数据指导生活,让算法服务于专注。

 

🚀 扩展方向

 

1. AR 实景叠加:将生成的 SVG 坐标通过手机 AR 投射到真实桌面上,实现“照着摆”。

2. 计算机视觉:接入摄像头,实时检测物品当前位置与算法推荐位置的偏差,发出语音提示。

3. 强化学习:根据用户实际的“寻找时间”反馈,动态调整频率评分权重。

 

利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值