pixel-office-openclaw 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +146 -0
- package/cli.js +167 -0
- package/dist/Screenshot.jpg +0 -0
- package/dist/assets/2dpig-LICENSE.txt +7 -0
- package/dist/assets/FSPixelSansUnicode-Regular-D9-dh-Uo.ttf +0 -0
- package/dist/assets/PixelOffice.png +0 -0
- package/dist/assets/PixelOfficeAssets.png +0 -0
- package/dist/assets/characters/char_0.png +0 -0
- package/dist/assets/characters/char_1.png +0 -0
- package/dist/assets/characters/char_2.png +0 -0
- package/dist/assets/characters/char_3.png +0 -0
- package/dist/assets/characters/char_4.png +0 -0
- package/dist/assets/characters/char_5.png +0 -0
- package/dist/assets/default-layout.json +98 -0
- package/dist/assets/index-D7SaYitc.js +15 -0
- package/dist/assets/index-DHX1xfjO.css +1 -0
- package/dist/assets/mockProvider-CjnCG90O.js +1 -0
- package/dist/assets/walls.png +0 -0
- package/dist/characters.png +0 -0
- package/dist/index.html +14 -0
- package/package.json +63 -0
- package/server.js +370 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Tridents Lab
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# 🏢 Pixel Office — by Tridents Lab 🔱
|
|
2
|
+
|
|
3
|
+
Watch your [OpenClaw](https://openclaw.ai) AI agents work in a pixel-art virtual office.
|
|
4
|
+
|
|
5
|
+
Each agent gets an animated character that walks around, sits at desks, and shows real-time status as they execute tasks. Click any agent to chat with them directly.
|
|
6
|
+
|
|
7
|
+
<!--  -->
|
|
8
|
+
|
|
9
|
+
## Quick Start
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx pixel-office-openclaw
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
That's it. Pixel Office auto-detects your local OpenClaw instance and starts a web server at `http://localhost:3002`.
|
|
16
|
+
|
|
17
|
+
> **No OpenClaw?** Try `npx pixel-office-openclaw --mock` to see it with simulated agents.
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- 🎮 **Pixel-art office** with animated characters and furniture
|
|
22
|
+
- 🔄 **Real-time status** — agents glow green when working, go idle when done
|
|
23
|
+
- 💬 **Chat** — click any agent to send them a message
|
|
24
|
+
- 🏗️ **Layout editor** — customize the office with desks, plants, bookshelves
|
|
25
|
+
- 🎨 **Role-based sprites** — coders, researchers, planners get distinct looks
|
|
26
|
+
- ✨ **Matrix animations** — spawn/despawn effects when agents come and go
|
|
27
|
+
- 📊 **Activity log** — see what your agents are doing in real-time
|
|
28
|
+
- 🖱️ **Interactive** — click agents to freeze them, hover for status tooltips
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
### Global install (recommended)
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install -g pixel-office-openclaw
|
|
36
|
+
pixel-office-openclaw
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### npx (no install)
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npx pixel-office-openclaw
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### From source
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
git clone https://github.com/neomatrix25/pixel-office.git
|
|
49
|
+
cd pixel-office
|
|
50
|
+
npm install
|
|
51
|
+
npm run build
|
|
52
|
+
npm start
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Configuration
|
|
56
|
+
|
|
57
|
+
Pixel Office auto-detects your OpenClaw setup. Override with CLI flags:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
pixel-office-openclaw [options]
|
|
61
|
+
|
|
62
|
+
Options:
|
|
63
|
+
-p, --port <number> Port (default: 3002)
|
|
64
|
+
--host <address> Bind address (default: 127.0.0.1)
|
|
65
|
+
--openclaw-home <path> OpenClaw home dir (default: ~/.openclaw)
|
|
66
|
+
--gateway-url <url> Gateway URL (auto-detected)
|
|
67
|
+
--gateway-token <token> Gateway token (auto-detected)
|
|
68
|
+
--no-chat Disable chat endpoint
|
|
69
|
+
--mock Demo mode with simulated agents
|
|
70
|
+
--open Open browser automatically
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Examples
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Default — auto-detect everything
|
|
77
|
+
pixel-office-openclaw
|
|
78
|
+
|
|
79
|
+
# Custom port
|
|
80
|
+
pixel-office-openclaw --port 8080
|
|
81
|
+
|
|
82
|
+
# Expose to your network (default is localhost only)
|
|
83
|
+
pixel-office-openclaw --host 0.0.0.0
|
|
84
|
+
|
|
85
|
+
# Demo mode — no OpenClaw needed
|
|
86
|
+
pixel-office-openclaw --mock
|
|
87
|
+
|
|
88
|
+
# Remote OpenClaw instance
|
|
89
|
+
pixel-office --gateway-url http://myserver:18789 --gateway-token mytoken
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Remote Access
|
|
93
|
+
|
|
94
|
+
By default, Pixel Office only listens on `127.0.0.1` (localhost). To access from other machines:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
pixel-office-openclaw --host 0.0.0.0
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
⚠️ **Security**: When exposed to a network, the server can read your agent sessions and send messages. Only expose on trusted networks.
|
|
101
|
+
|
|
102
|
+
## How It Works
|
|
103
|
+
|
|
104
|
+
Pixel Office runs a lightweight Express server that:
|
|
105
|
+
|
|
106
|
+
1. **Reads agent session stores** from `~/.openclaw/agents/*/sessions/sessions.json`
|
|
107
|
+
2. **Deduplicates sessions** — one character per agent, using the most recently active session
|
|
108
|
+
3. **Serves a React app** that renders a pixel-art office on HTML Canvas
|
|
109
|
+
4. **Polls every 3 seconds** for status updates
|
|
110
|
+
5. **Proxies chat messages** to agents via the OpenClaw gateway API
|
|
111
|
+
|
|
112
|
+
No data leaves your machine. The gateway token stays server-side and is never sent to the browser.
|
|
113
|
+
|
|
114
|
+
## Layout Editor
|
|
115
|
+
|
|
116
|
+
Click the **Edit** button (bottom toolbar) to customize your office:
|
|
117
|
+
|
|
118
|
+
- 🎨 Paint floor tiles and walls
|
|
119
|
+
- 🪑 Place furniture (desks, chairs, plants, bookshelves)
|
|
120
|
+
- ↩️ Undo/redo (Ctrl+Z / Ctrl+Y)
|
|
121
|
+
- 🔄 Rotate items (R key)
|
|
122
|
+
- 💾 Save your layout
|
|
123
|
+
|
|
124
|
+
## Requirements
|
|
125
|
+
|
|
126
|
+
- **Node.js 18+**
|
|
127
|
+
- **OpenClaw** running locally (or use `--mock` for demo)
|
|
128
|
+
|
|
129
|
+
## Tech Stack
|
|
130
|
+
|
|
131
|
+
- React 19 + TypeScript
|
|
132
|
+
- Canvas 2D rendering (no WebGL)
|
|
133
|
+
- Vite for builds
|
|
134
|
+
- Express 5 for the bridge server
|
|
135
|
+
- A* pathfinding for character navigation
|
|
136
|
+
|
|
137
|
+
## License
|
|
138
|
+
|
|
139
|
+
MIT — see [LICENSE](LICENSE)
|
|
140
|
+
|
|
141
|
+
## Credits
|
|
142
|
+
|
|
143
|
+
Built by [Tridents Lab](https://github.com/neomatrix25) 🔱
|
|
144
|
+
|
|
145
|
+
Character sprites based on [pixel-agents](https://github.com/pablodelucca/pixel-agents) (MIT).
|
|
146
|
+
Office furniture sprites by [2dPig](https://2dpig.itch.io) (CC0 Public Domain).
|
package/cli.js
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Pixel Office CLI — visualize OpenClaw agents in a pixel-art office.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* pixel-office [options]
|
|
7
|
+
*
|
|
8
|
+
* Options:
|
|
9
|
+
* -p, --port <number> Port to listen on (default: 3002)
|
|
10
|
+
* -h, --host <address> Bind address (default: 127.0.0.1)
|
|
11
|
+
* --openclaw-home <path> OpenClaw home directory (default: ~/.openclaw)
|
|
12
|
+
* --gateway-url <url> Gateway URL (auto-detected from config)
|
|
13
|
+
* --gateway-token <token> Gateway token (auto-detected from config)
|
|
14
|
+
* --no-chat Disable chat send endpoint
|
|
15
|
+
* --mock Start with mock mode (no OpenClaw needed)
|
|
16
|
+
* --open Open browser after starting
|
|
17
|
+
* -v, --version Show version
|
|
18
|
+
* --help Show this help
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { readFileSync, existsSync } from 'fs'
|
|
22
|
+
import { join } from 'path'
|
|
23
|
+
import { homedir } from 'os'
|
|
24
|
+
import { fileURLToPath } from 'url'
|
|
25
|
+
import { dirname } from 'path'
|
|
26
|
+
import { execSync } from 'child_process'
|
|
27
|
+
|
|
28
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
29
|
+
const __dirname = dirname(__filename)
|
|
30
|
+
|
|
31
|
+
// ── Argument Parsing ────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
const args = process.argv.slice(2)
|
|
34
|
+
|
|
35
|
+
function getArg(flags, defaultValue = undefined) {
|
|
36
|
+
for (let i = 0; i < args.length; i++) {
|
|
37
|
+
if (flags.includes(args[i]) && i + 1 < args.length) {
|
|
38
|
+
return args[i + 1]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return defaultValue
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function hasFlag(flags) {
|
|
45
|
+
return args.some(a => flags.includes(a))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (hasFlag(['--help'])) {
|
|
49
|
+
console.log(`
|
|
50
|
+
Pixel Office — Watch your OpenClaw agents work in a pixel-art office 🦞
|
|
51
|
+
|
|
52
|
+
Usage: pixel-office [options]
|
|
53
|
+
|
|
54
|
+
Options:
|
|
55
|
+
-p, --port <number> Port to listen on (default: 3002)
|
|
56
|
+
--host <address> Bind address (default: 127.0.0.1)
|
|
57
|
+
--openclaw-home <path> OpenClaw home dir (default: ~/.openclaw)
|
|
58
|
+
--gateway-url <url> Gateway URL (auto-detected)
|
|
59
|
+
--gateway-token <token> Gateway token (auto-detected)
|
|
60
|
+
--no-chat Disable chat/send endpoint
|
|
61
|
+
--mock Mock mode (no OpenClaw needed)
|
|
62
|
+
--no-open Don't open browser after starting
|
|
63
|
+
-v, --version Show version
|
|
64
|
+
--help Show this help
|
|
65
|
+
|
|
66
|
+
Examples:
|
|
67
|
+
pixel-office # Auto-detect local OpenClaw
|
|
68
|
+
pixel-office --port 8080 # Custom port
|
|
69
|
+
pixel-office --host 0.0.0.0 # Expose to network
|
|
70
|
+
pixel-office --mock # Demo without OpenClaw
|
|
71
|
+
`)
|
|
72
|
+
process.exit(0)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (hasFlag(['-v', '--version'])) {
|
|
76
|
+
try {
|
|
77
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf-8'))
|
|
78
|
+
console.log(`pixel-office v${pkg.version}`)
|
|
79
|
+
} catch {
|
|
80
|
+
console.log('pixel-office (unknown version)')
|
|
81
|
+
}
|
|
82
|
+
process.exit(0)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ── Configuration ───────────────────────────────────────────────
|
|
86
|
+
|
|
87
|
+
const PORT = parseInt(getArg(['-p', '--port'], '3002'), 10)
|
|
88
|
+
const HOST = getArg(['--host'], '127.0.0.1')
|
|
89
|
+
const OPENCLAW_HOME = getArg(['--openclaw-home'], join(homedir(), '.openclaw'))
|
|
90
|
+
const CHAT_DISABLED = hasFlag(['--no-chat'])
|
|
91
|
+
const MOCK_MODE = hasFlag(['--mock'])
|
|
92
|
+
const OPEN_BROWSER = !hasFlag(['--no-open'])
|
|
93
|
+
|
|
94
|
+
// ── Auto-detect Gateway ─────────────────────────────────────────
|
|
95
|
+
|
|
96
|
+
function autoDetectGateway() {
|
|
97
|
+
const configPath = join(OPENCLAW_HOME, 'openclaw.json')
|
|
98
|
+
if (!existsSync(configPath)) return { url: null, token: null }
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
const config = JSON.parse(readFileSync(configPath, 'utf-8'))
|
|
102
|
+
const gw = config.gateway || {}
|
|
103
|
+
const port = gw.port || 18789
|
|
104
|
+
const token = gw.auth?.token || null
|
|
105
|
+
const url = `http://127.0.0.1:${port}`
|
|
106
|
+
return { url, token }
|
|
107
|
+
} catch (err) {
|
|
108
|
+
console.warn('[pixel-office] Could not read OpenClaw config:', err.message)
|
|
109
|
+
return { url: null, token: null }
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
let GATEWAY_URL = getArg(['--gateway-url'])
|
|
114
|
+
let GATEWAY_TOKEN = getArg(['--gateway-token'])
|
|
115
|
+
|
|
116
|
+
if (!GATEWAY_URL || !GATEWAY_TOKEN) {
|
|
117
|
+
const detected = autoDetectGateway()
|
|
118
|
+
if (!GATEWAY_URL) GATEWAY_URL = detected.url
|
|
119
|
+
if (!GATEWAY_TOKEN) GATEWAY_TOKEN = detected.token
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ── Export config and start server ──────────────────────────────
|
|
123
|
+
|
|
124
|
+
process.env.PORT = String(PORT)
|
|
125
|
+
process.env.PIXEL_OFFICE_HOST = HOST
|
|
126
|
+
process.env.OPENCLAW_HOME = OPENCLAW_HOME
|
|
127
|
+
if (GATEWAY_URL) process.env.OPENCLAW_GATEWAY_URL = GATEWAY_URL
|
|
128
|
+
if (GATEWAY_TOKEN) process.env.OPENCLAW_GATEWAY_TOKEN = GATEWAY_TOKEN
|
|
129
|
+
if (CHAT_DISABLED) process.env.PIXEL_OFFICE_NO_CHAT = '1'
|
|
130
|
+
|
|
131
|
+
// Print startup banner
|
|
132
|
+
console.log('')
|
|
133
|
+
console.log(' 🏢 Pixel Office')
|
|
134
|
+
console.log(' ────────────────────────────────')
|
|
135
|
+
if (MOCK_MODE) {
|
|
136
|
+
console.log(' Mode: Mock (no OpenClaw needed)')
|
|
137
|
+
} else {
|
|
138
|
+
console.log(` OpenClaw: ${OPENCLAW_HOME}`)
|
|
139
|
+
console.log(` Gateway: ${GATEWAY_URL || '(not detected)'}`)
|
|
140
|
+
console.log(` Token: ${GATEWAY_TOKEN ? '(configured)' : '(not detected)'}`)
|
|
141
|
+
}
|
|
142
|
+
console.log(` Server: http://${HOST}:${PORT}`)
|
|
143
|
+
console.log(` Chat: ${CHAT_DISABLED ? 'disabled' : 'enabled'}`)
|
|
144
|
+
console.log(' ────────────────────────────────')
|
|
145
|
+
console.log('')
|
|
146
|
+
|
|
147
|
+
if (!MOCK_MODE && !GATEWAY_URL) {
|
|
148
|
+
console.warn(' ⚠️ No OpenClaw instance detected.')
|
|
149
|
+
console.warn(' Make sure OpenClaw is running, or pass --gateway-url and --gateway-token.')
|
|
150
|
+
console.warn(' Starting anyway — you can connect via the UI.\n')
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Open browser after a short delay
|
|
154
|
+
if (OPEN_BROWSER) {
|
|
155
|
+
setTimeout(() => {
|
|
156
|
+
const url = `http://localhost:${PORT}`
|
|
157
|
+
try {
|
|
158
|
+
const platform = process.platform
|
|
159
|
+
if (platform === 'darwin') execSync(`open ${url}`)
|
|
160
|
+
else if (platform === 'win32') execSync(`start ${url}`)
|
|
161
|
+
else execSync(`xdg-open ${url} 2>/dev/null || sensible-browser ${url} 2>/dev/null`)
|
|
162
|
+
} catch { /* ignore */ }
|
|
163
|
+
}, 1000)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Import and start the server
|
|
167
|
+
import('./server.js')
|
|
Binary file
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
This asset pack is released under the Creative Commons Public Domain Dedication License (aka CC0 or CC Zero).
|
|
2
|
+
|
|
3
|
+
CC0 is a public dedication tool, which allows creators to give up their copyright and put their works into the worldwide public domain. CC0 allows users to distribute, remix, adapt, and build upon the material in any medium or format, with no conditions.
|
|
4
|
+
|
|
5
|
+
More info here:
|
|
6
|
+
https://creativecommons.org/publicdomain/zero/1.0/
|
|
7
|
+
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"cols": 20,
|
|
4
|
+
"rows": 12,
|
|
5
|
+
"tiles": [
|
|
6
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
7
|
+
0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 3, 3, 3, 3, 0,
|
|
8
|
+
0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 3, 3, 3, 3, 0,
|
|
9
|
+
0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 3, 3, 3, 3, 0,
|
|
10
|
+
0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 3, 3, 3, 3, 0,
|
|
11
|
+
0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 0, 3, 3, 3, 3, 0,
|
|
12
|
+
0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
|
|
13
|
+
0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
|
|
14
|
+
0, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 0,
|
|
15
|
+
0, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 0,
|
|
16
|
+
0, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 0,
|
|
17
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
18
|
+
],
|
|
19
|
+
"furniture": [
|
|
20
|
+
{"uid": "desk-1-1", "type": "desk", "col": 1, "row": 1},
|
|
21
|
+
{"uid": "chair-1-3", "type": "chair", "col": 2, "row": 3},
|
|
22
|
+
{"uid": "chair-1-4", "type": "chair", "col": 1, "row": 3},
|
|
23
|
+
{"uid": "pc-1-1", "type": "pc", "col": 1, "row": 1},
|
|
24
|
+
{"uid": "pc-1-2", "type": "pc", "col": 2, "row": 1},
|
|
25
|
+
|
|
26
|
+
{"uid": "desk-4-1", "type": "desk", "col": 4, "row": 1},
|
|
27
|
+
{"uid": "chair-4-3", "type": "chair", "col": 5, "row": 3},
|
|
28
|
+
{"uid": "chair-4-4", "type": "chair", "col": 4, "row": 3},
|
|
29
|
+
{"uid": "pc-4-1", "type": "pc", "col": 4, "row": 1},
|
|
30
|
+
{"uid": "pc-4-2", "type": "pc", "col": 5, "row": 1},
|
|
31
|
+
|
|
32
|
+
{"uid": "desk-1-4", "type": "desk", "col": 1, "row": 4},
|
|
33
|
+
{"uid": "chair-1-6", "type": "chair", "col": 2, "row": 6},
|
|
34
|
+
{"uid": "chair-1-7", "type": "chair", "col": 1, "row": 6},
|
|
35
|
+
{"uid": "pc-1-4", "type": "pc", "col": 1, "row": 4},
|
|
36
|
+
|
|
37
|
+
{"uid": "desk-4-4", "type": "desk", "col": 4, "row": 4},
|
|
38
|
+
{"uid": "chair-4-6", "type": "chair", "col": 5, "row": 6},
|
|
39
|
+
{"uid": "chair-4-7", "type": "chair", "col": 4, "row": 6},
|
|
40
|
+
{"uid": "pc-4-4", "type": "pc", "col": 4, "row": 4},
|
|
41
|
+
|
|
42
|
+
{"uid": "desk-9-1", "type": "desk", "col": 9, "row": 1},
|
|
43
|
+
{"uid": "chair-9-3", "type": "chair", "col": 10, "row": 3},
|
|
44
|
+
{"uid": "chair-9-4", "type": "chair", "col": 9, "row": 3},
|
|
45
|
+
{"uid": "pc-9-1", "type": "pc", "col": 9, "row": 1},
|
|
46
|
+
{"uid": "pc-9-2", "type": "pc", "col": 10, "row": 1},
|
|
47
|
+
|
|
48
|
+
{"uid": "desk-11-1", "type": "desk", "col": 11, "row": 1},
|
|
49
|
+
{"uid": "chair-11-3", "type": "chair", "col": 12, "row": 3},
|
|
50
|
+
{"uid": "chair-11-4", "type": "chair", "col": 11, "row": 3},
|
|
51
|
+
{"uid": "pc-11-1", "type": "pc", "col": 11, "row": 1},
|
|
52
|
+
{"uid": "pc-11-2", "type": "pc", "col": 12, "row": 1},
|
|
53
|
+
|
|
54
|
+
{"uid": "wb-15-1", "type": "whiteboard", "col": 15, "row": 1},
|
|
55
|
+
{"uid": "chair-15-3", "type": "chair", "col": 15, "row": 3},
|
|
56
|
+
{"uid": "chair-16-3", "type": "chair", "col": 16, "row": 3},
|
|
57
|
+
{"uid": "chair-17-3", "type": "chair", "col": 17, "row": 3},
|
|
58
|
+
{"uid": "chair-18-3", "type": "chair", "col": 18, "row": 3},
|
|
59
|
+
|
|
60
|
+
{"uid": "desk-1-8", "type": "desk", "col": 1, "row": 8},
|
|
61
|
+
{"uid": "chair-1-8s", "type": "chair", "col": 1, "row": 8},
|
|
62
|
+
{"uid": "chair-2-8s", "type": "chair", "col": 2, "row": 8},
|
|
63
|
+
{"uid": "pc-1-8", "type": "pc", "col": 1, "row": 8},
|
|
64
|
+
|
|
65
|
+
{"uid": "desk-4-8", "type": "desk", "col": 4, "row": 8},
|
|
66
|
+
{"uid": "chair-4-8s", "type": "chair", "col": 4, "row": 8},
|
|
67
|
+
{"uid": "chair-5-8s", "type": "chair", "col": 5, "row": 8},
|
|
68
|
+
{"uid": "pc-4-8", "type": "pc", "col": 4, "row": 8},
|
|
69
|
+
|
|
70
|
+
{"uid": "desk-12-8", "type": "desk", "col": 12, "row": 8},
|
|
71
|
+
{"uid": "chair-12-8s", "type": "chair", "col": 12, "row": 8},
|
|
72
|
+
{"uid": "chair-13-8s", "type": "chair", "col": 13, "row": 8},
|
|
73
|
+
{"uid": "pc-12-8", "type": "pc", "col": 12, "row": 8},
|
|
74
|
+
|
|
75
|
+
{"uid": "desk-15-8", "type": "desk", "col": 15, "row": 8},
|
|
76
|
+
{"uid": "chair-15-8s", "type": "chair", "col": 15, "row": 8},
|
|
77
|
+
{"uid": "chair-16-8s", "type": "chair", "col": 16, "row": 8},
|
|
78
|
+
{"uid": "pc-15-8", "type": "pc", "col": 15, "row": 8},
|
|
79
|
+
|
|
80
|
+
{"uid": "plant-7-1", "type": "plant", "col": 7, "row": 1},
|
|
81
|
+
{"uid": "plant-7-6", "type": "plant", "col": 7, "row": 7},
|
|
82
|
+
{"uid": "plant-14-6", "type": "plant", "col": 14, "row": 7},
|
|
83
|
+
{"uid": "plant-8-10", "type": "plant", "col": 8, "row": 10},
|
|
84
|
+
{"uid": "plant-11-10", "type": "plant", "col": 11, "row": 10},
|
|
85
|
+
{"uid": "plant-1-7", "type": "plant", "col": 1, "row": 7},
|
|
86
|
+
|
|
87
|
+
{"uid": "cooler-8-7", "type": "cooler", "col": 9, "row": 7},
|
|
88
|
+
|
|
89
|
+
{"uid": "bs-7-8", "type": "bookshelf", "col": 7, "row": 8},
|
|
90
|
+
{"uid": "bs-7-10", "type": "bookshelf", "col": 7, "row": 10},
|
|
91
|
+
{"uid": "bs-18-8", "type": "bookshelf", "col": 18, "row": 8},
|
|
92
|
+
{"uid": "bs-18-10", "type": "bookshelf", "col": 18, "row": 10},
|
|
93
|
+
|
|
94
|
+
{"uid": "lamp-13-1", "type": "lamp", "col": 13, "row": 2},
|
|
95
|
+
{"uid": "lamp-18-7", "type": "lamp", "col": 18, "row": 7},
|
|
96
|
+
{"uid": "lamp-6-7", "type": "lamp", "col": 6, "row": 7}
|
|
97
|
+
]
|
|
98
|
+
}
|