> For the complete documentation index, see [llms.txt](https://kopens.gitbook.io/plantpulse-platform/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kopens.gitbook.io/plantpulse-platform/developer/plugin-ram.md).

# RAM 계산 로직 상세

## 개요 <a href="#overview" id="overview"></a>

RAM(Reliability, Availability, Maintainability)은 ISO 14224 표준에 기반하여 설비의 고장 패턴을 분석하고 정비 지표를 산출하는 플러그인입니다. 설비가 얼마나 오래 고장 없이 가동되는지(신뢰성), 전체 시간 중 사용 가능한 비율(가용성), 고장 시 얼마나 빨리 복구되는지(정비성)를 정량적으로 분석합니다.

이 문서에서는 RAM 계산에 사용되는 수식, 입력 데이터, 내부 처리 로직을 상세히 설명합니다.

***

## 핵심 계산식 <a href="#formula" id="formula"></a>

RAM은 6가지 핵심 지표를 산출합니다. 모든 지표는 **지수분포(Exponential Distribution)** 모델을 기반으로 합니다.

### 지표 간 관계도

```
                 총 운전 시간, 고장 횟수
                         │
                         ▼
                   ┌──────────┐
                   │   MTBF   │ ← 평균 고장 간격
                   └──────────┘
                    │         │
            ┌───────┘         └───────┐
            ▼                         ▼
     ┌──────────────┐         ┌──────────────┐
     │  고장률 (λ)   │         │  신뢰도 R(t)  │
     │  = 1/MTBF    │         │  = e^(-t/MTBF)│
     └──────────────┘         └──────────────┘

                총 수리 시간, 수리 횟수
                         │
                         ▼
                   ┌──────────┐
                   │   MTTR   │ ← 평균 수리 시간
                   └──────────┘
                         │
                         ▼
                  ┌──────────────┐
                  │ 정비성 M(t)   │
                  │= 1-e^(-t/MTTR)│
                  └──────────────┘

                  MTBF + MTTR
                       │
                       ▼
               ┌──────────────┐
               │ 정비 가용도    │
               │ MA=MTBF/     │
               │  (MTBF+MTTR) │
               └──────────────┘
```

***

### MTBF (평균 고장 간격) <a href="#mtbf" id="mtbf"></a>

**Mean Time Between Failures** — 설비가 평균적으로 얼마나 오래 정상 가동한 후 고장이 발생하는지를 나타냅니다.

```
         총 운전 시간 (sec)
MTBF = ─────────────────────
           고장 횟수
```

| 항목      | 설명                        | 소스                                     |
| ------- | ------------------------- | -------------------------------------- |
| 총 운전 시간 | OEE의 `run_time_ms / 1000` | OEE 계산 결과 참조                           |
| 고장 횟수   | `FAILURE_START` 이벤트 발생 수  | Cassandra `tm_asset_ram_failure_event` |

* 단위: 초(sec), 시간(hours) 병기
* 고장 횟수가 0이면 MTBF = `0.0`
* **값이 클수록 설비 신뢰성이 높음**

**예시:**

* 총 운전 시간: 180,000초 (50시간)
* 고장 횟수: 5회
* **MTBF = 180,000 / 5 = 36,000초 (10시간)**
* 평균 10시간마다 고장이 발생한다는 의미

***

### MTTR (평균 수리 시간) <a href="#mttr" id="mttr"></a>

**Mean Time To Repair** — 고장 발생 후 수리 완료까지 평균적으로 걸리는 시간입니다.

```
         총 수리 시간 (sec)
MTTR = ─────────────────────
           수리 횟수
```

| 항목      | 설명                                            | 소스                                     |
| ------- | --------------------------------------------- | -------------------------------------- |
| 총 수리 시간 | `FAILURE_START` \~ `FAILURE_END` 간격의 합 / 1000 | Cassandra 고장 이벤트 쌍 매칭                  |
| 수리 횟수   | `FAILURE_END` 이벤트 발생 수 (완료된 수리)               | Cassandra `tm_asset_ram_failure_event` |

* 단위: 초(sec), 시간(hours) 병기
* 수리 횟수가 0이면 MTTR = `0.0`
* **값이 작을수록 정비 능력이 우수**

**예시:**

* 총 수리 시간: 9,000초 (2.5시간)
* 수리 횟수: 5회
* **MTTR = 9,000 / 5 = 1,800초 (0.5시간 = 30분)**
* 고장당 평균 30분이면 수리 완료

***

### MA (정비 가용도) <a href="#ma" id="ma"></a>

**Maintenance Availability** — 설비가 임의의 시점에 가동 가능한 상태에 있을 확률입니다.

```
            MTBF
MA = ─────────────────
       MTBF + MTTR
```

* 범위: `0.0 ~ 1.0`
* MTBF와 MTTR이 모두 0이면 MA = `0.0`
* **1.0에 가까울수록 설비를 오래 사용할 수 있음**

**예시:**

* MTBF: 36,000초, MTTR: 1,800초
* **MA = 36,000 / (36,000 + 1,800) = 0.9524 (95.24%)**
* 전체 시간의 약 95%는 설비 사용 가능

***

### 고장률 lambda (Failure Rate) <a href="#failure-rate" id="failure-rate"></a>

단위 시간당 고장 발생 확률입니다. 지수분포 모델에서의 순간 고장률을 나타냅니다.

```
λ = 1 / MTBF   (단위: failures/sec)
```

* MTBF가 0이면 λ = `0.0`
* **값이 작을수록 고장이 드물게 발생**

**예시:**

* MTBF: 36,000초
* **λ = 1 / 36,000 = 0.00002778 failures/sec**

***

### R(t) — 신뢰도 함수 <a href="#reliability" id="reliability"></a>

주어진 시간 `t` 동안 설비가 고장 없이 가동될 확률입니다. 지수분포의 생존함수(Survival Function)에 해당합니다.

```
R(t) = e^(-t / MTBF)
```

* 기본 계산: **t = 3,600초 (1시간)**
* MTBF가 0이면 R(t) = `0.0`
* 범위: `0.0 ~ 1.0`

**예시:**

* MTBF: 36,000초, t: 3,600초
* **R(1h) = e^(-3600/36000) = e^(-0.1) = 0.9048**
* 1시간 동안 고장 없이 가동될 확률: 약 90.5%

### 신뢰도 해석 참고

| R(1h) 값      | 해석                   |
| ------------ | -------------------- |
| 0.95 이상      | 매우 신뢰성 높은 설비         |
| 0.90 \~ 0.95 | 양호한 수준               |
| 0.80 \~ 0.90 | 주의 필요, 예방 정비 강화 권장   |
| 0.80 미만      | 심각한 수준, 설비 교체/대수리 검토 |

***

### M(t) — 정비성 함수 <a href="#maintainability" id="maintainability"></a>

주어진 시간 `t` 이내에 수리가 완료될 확률입니다. 지수분포의 CDF(누적분포함수)에 해당합니다.

```
M(t) = 1 - e^(-t / MTTR)
```

* 기본 계산: **t = 3,600초 (1시간)**
* MTTR이 0이면 M(t) = `0.0`
* 범위: `0.0 ~ 1.0`

**예시:**

* MTTR: 1,800초, t: 3,600초
* **M(1h) = 1 - e^(-3600/1800) = 1 - e^(-2) = 0.8647**
* 1시간 이내에 수리가 완료될 확률: 약 86.5%

### 정비성 해석 참고

| M(1h) 값      | 해석                 |
| ------------ | ------------------ |
| 0.95 이상      | 정비 체계 매우 우수        |
| 0.80 \~ 0.95 | 양호한 수준             |
| 0.60 \~ 0.80 | 정비 체계 개선 필요        |
| 0.60 미만      | 부품/인력/도구 전면 재검토 필요 |

***

## 입력 데이터 <a href="#input-data" id="input-data"></a>

### 데이터 흐름

```
센서/PLC
  │
  ▼
CEP Engine (EQL 룰)
  │
  ├── FAILURE_START 이벤트 → 고장 시작 기록
  │                           (Cassandra tm_asset_ram_failure_event)
  │
  └── FAILURE_END 이벤트 → 고장 종료 기록 + RAM 재계산 트리거
                             │
                             ▼
                      RAMFailureHandler
                             │
                      ┌──────┼──────┐
                      ▼      ▼      ▼
                   고장통계  OEE참조  RAM계산
                   조회     (run_time) 실행
                             │
                             ▼
                    mm_order_ram UPSERT
                    + RAMCalculatedEvent 발행
```

### 고장 통계 (RAMFaultStatsDTO)

Cassandra `tm_asset_ram_failure_event` 테이블에서 집계합니다.

| 필드                     | 타입   | 설명                              |
| ---------------------- | ---- | ------------------------------- |
| `failure_count`        | long | FAILURE\_START 이벤트 발생 횟수        |
| `repair_count`         | long | FAILURE\_END 이벤트 발생 횟수 (완료된 수리) |
| `total_repair_time_ms` | long | 모든 수리 시간의 합 (ms)                |

### 운전 시간

OEE 계산 결과에서 `run_time_ms`를 참조합니다.

```
total_run_time_sec = OEE.run_time_ms / 1000.0
```

RAM은 OEE에 의존하므로, OEE 데이터가 없으면 RAM 계산이 수행되지 않습니다.

***

## 이벤트 및 트리거 <a href="#events" id="events"></a>

### 고장 이벤트 키

| 키               | 값                 | 발행 시점                 |
| --------------- | ----------------- | --------------------- |
| `FAILURE_START` | `"FAILURE_START"` | 설비 고장 감지 시 (CEP 룰 매칭) |
| `FAILURE_END`   | `"FAILURE_END"`   | 수리 완료 시 (CEP 룰 매칭)    |

### 재계산 트리거

RAM 지표는 다음 두 가지 경우에 재계산됩니다:

1. **이벤트 기반**: `FAILURE_END` 이벤트 수신 시 `RAMFailureHandler`가 즉시 재계산
2. **스케줄 기반**: `RAMCalculationJob`이 10초 주기로 활성 주문의 모든 설비에 대해 일괄 계산 (5 병렬 스레드)

***

## 계산 흐름 (8단계) <a href="#calculation-flow" id="calculation-flow"></a>

```
calculate(asset_id, run_time_sec, from_ts, to_ts)
│
├── 1. 고장 통계 조회
│      selectAssetFaultStats(asset_id, from_ts, to_ts)
│      → failure_count, repair_count, total_repair_time_ms
│
├── 2. MTBF 계산
│      mtbf_sec = total_run_time_sec / failure_count
│      (failure_count = 0 이면 0.0)
│
├── 3. MTTR 계산
│      mttr_sec = total_repair_time_sec / repair_count
│      (repair_count = 0 이면 0.0)
│
├── 4. 정비 가용도 (MA)
│      ma = mtbf_sec / (mtbf_sec + mttr_sec)
│
├── 5. 고장률 (λ)
│      lambda = 1.0 / mtbf_sec
│
├── 6. 신뢰도 R(t=1h)
│      R = e^(-3600 / mtbf_sec)
│
├── 7. 정비성 M(t=1h)
│      M = 1 - e^(-3600 / mttr_sec)
│
└── 8. 결과 조립 + 저장
       ├── PostgreSQL mm_order_ram UPSERT
       ├── Cassandra 듀얼 라이트
       └── RAMCalculatedEvent 발행
```

***

## 데이터베이스 스키마 <a href="#database" id="database"></a>

### PostgreSQL — mm\_order\_ram

주문별 최신 RAM 스냅샷을 UPSERT 방식으로 관리합니다. PK는 `order_id`입니다.

| 컬럼                            | 타입        | 설명           |
| ----------------------------- | --------- | ------------ |
| `order_id`                    | varchar   | 작업지시 ID (PK) |
| `insert_timestamp`            | timestamp | 저장 시각        |
| `site_id`                     | varchar   | 사이트 ID       |
| `area_id`                     | varchar   | 영역 ID        |
| `line_id`                     | varchar   | 라인 ID        |
| `asset_id`                    | varchar   | 설비 ID        |
| `mtbf_sec`                    | double    | MTBF (초)     |
| `mtbf_hours`                  | double    | MTBF (시간)    |
| `mttr_sec`                    | double    | MTTR (초)     |
| `mttr_hours`                  | double    | MTTR (시간)    |
| `maintenance_availability`    | double    | 정비 가용도 (MA)  |
| `failure_rate_lambda_per_sec` | double    | 고장률 λ (/초)   |
| `reliability_r_1h`            | double    | 신뢰도 R(1h)    |
| `maintainability_m_1h`        | double    | 정비성 M(1h)    |
| `failure_count`               | long      | 고장 횟수        |
| `repair_count`                | long      | 수리 완료 횟수     |
| `total_run_time_hours`        | double    | 총 운전 시간 (시간) |
| `last_calculated_timestamp`   | timestamp | 마지막 계산 시각    |
| `payload`                     | jsonb     | 전체 결과 JSON   |

### Cassandra

| 테이블                                 | PK                                                     | 용도                                     |
| ----------------------------------- | ------------------------------------------------------ | -------------------------------------- |
| `tm_asset_ram`                      | `(site_id), area_id, line_id, asset_id, order_id`      | 설비별 RAM 최신 지표                          |
| `tm_asset_ram_history`              | `(asset_id), order_id, year, month, day, hour, minute` | RAM 이력                                 |
| `tm_asset_ram_history_by_timestamp` | `(asset_id), timestamp`                                | 타임스탬프 기반 조회                            |
| `tm_asset_ram_failure_event`        | `(asset_id), timestamp`                                | 고장 이벤트 원본 (`event_type`, `fault_code`) |

***

## 출력 정밀도 <a href="#precision" id="precision"></a>

모든 수치 결과는 Apache Commons Math `Precision.round()`를 사용합니다.

| 지표                            | 소수점 자릿수 |
| ----------------------------- | ------- |
| `mtbf_sec`, `mttr_sec`        | 3자리     |
| `mtbf_hours`, `mttr_hours`    | 3자리     |
| `maintenance_availability`    | 4자리     |
| `failure_rate_lambda_per_sec` | 8자리     |
| `reliability_R_1h`            | 6자리     |
| `maintainability_M_1h`        | 6자리     |
| `total_run_time_hours`        | 3자리     |

***

## 종합 예시 <a href="#example" id="example"></a>

아래는 하나의 작업지시 기간(50시간 운전, 고장 5회) 동안의 RAM 계산 결과 예시입니다.

| 입력                     | 값               |
| ---------------------- | --------------- |
| 총 운전 시간                | 180,000초 (50시간) |
| 고장 횟수 (FAILURE\_START) | 5회              |
| 수리 횟수 (FAILURE\_END)   | 5회              |
| 총 수리 시간                | 9,000초 (2.5시간)  |

| 지표    | 계산                        | 결과                 |
| ----- | ------------------------- | ------------------ |
| MTBF  | 180,000 / 5               | **36,000초 (10시간)** |
| MTTR  | 9,000 / 5                 | **1,800초 (0.5시간)** |
| MA    | 36,000 / (36,000 + 1,800) | **0.9524**         |
| λ     | 1 / 36,000                | **0.00002778 /초**  |
| R(1h) | e^(-3600/36000)           | **0.9048**         |
| M(1h) | 1 - e^(-3600/1800)        | **0.8647**         |

### 해석

* 설비는 평균 **10시간**마다 고장이 발생합니다
* 고장 시 평균 **30분**이면 수리가 완료됩니다
* 전체 시간의 \*\*95.24%\*\*는 설비를 사용할 수 있습니다
* 향후 1시간 동안 고장 없이 가동될 확률은 \*\*90.48%\*\*입니다
* 고장 발생 시 1시간 이내 수리 완료 확률은 \*\*86.47%\*\*입니다

***

## OEE 의존 관계 <a href="#oee-dependency" id="oee-dependency"></a>

RAM은 OEE 데이터에 의존합니다:

```
OEE Calculator
    │
    ├── run_time_ms  ──────▶  RAM의 운전 시간 (total_run_time_sec)
    │
    └── 활성 주문 정보 ──────▶  RAM의 집계 윈도우 (from_ts, to_ts)
```

* OEE가 계산되지 않은 설비에서는 RAM도 계산되지 않습니다
* RAM의 운전 시간은 OEE의 RUN 상태 누적 시간을 그대로 사용합니다
