openapi: 3.0.3
info:
  title: Rubric Management API
  description: |
    ルーブリック管理システムのREST API仕様

    このAPIは、ルーブリック（評価基準表）の作成、編集、削除、および閲覧機能を提供します。
    すべてのエンドポイントは認証が必要で、CSRF保護が有効になっています。
  version: 1.0.0
  contact:
    name: API Support
    email: support@example.com

servers:
  - url: http://localhost
    description: ローカル開発環境

security:
  - cookieAuth: []
  - csrfToken: []

tags:
  - name: Rubrics
    description: ルーブリック管理
  - name: Views
    description: HTMLビュー

paths:
  /rubric:
    get:
      tags:
        - Views
      summary: ルーブリック一覧表示
      description: ログインユーザーが作成したルーブリックの一覧を表示します
      operationId: listRubrics
      parameters:
        - name: show_all
          in: query
          description: true/1の場合、子ルーブリックも表示
          required: false
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: 成功
          content:
            text/html:
              schema:
                type: string
        '401':
          $ref: '#/components/responses/Unauthorized'

  /rubric/create:
    get:
      tags:
        - Views
      summary: ルーブリック作成フォーム表示
      description: ルーブリック作成画面を表示します
      operationId: showCreateForm
      responses:
        '200':
          description: 成功
          content:
            text/html:
              schema:
                type: string
        '401':
          $ref: '#/components/responses/Unauthorized'

  /rubric/store:
    post:
      tags:
        - Rubrics
      summary: ルーブリック作成
      description: 新しいルーブリックを作成します
      operationId: storeRubric
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RubricCreateRequest'
            examples:
              basic:
                summary: 基本的なルーブリック
                value:
                  title: "情報リテラシー評価"
                  description: "情報リテラシーの評価ルーブリック"
                  attribute: "評価項目"
                  level: "優れている,良い,努力が必要"
                  criteria:
                    - item: "情報の正確性"
                      category_id: null
                      performances:
                        - descriptor: "信頼できる情報源から正確な情報を収集できる"
                          point: 3
                        - descriptor: "おおむね正確な情報を収集できる"
                          point: 2
                        - descriptor: "情報の正確性に課題がある"
                          point: 1
              withCategories:
                summary: カテゴリ付きルーブリック
                value:
                  title: "プレゼンテーション評価"
                  description: "プレゼンテーション能力の評価"
                  attribute: "評価項目"
                  level: "優,良,可"
                  categories:
                    - title: "話の構成"
                    - title: "話し方"
                  criteria:
                    - item: "論理的な構成"
                      category_id: 0
                      performances:
                        - descriptor: "論理的で分かりやすい構成"
                          point: 3
                        - descriptor: "おおむね論理的な構成"
                          point: 2
                    - item: "声の大きさ"
                      category_id: 1
                      performances:
                        - descriptor: "適切な声の大きさ"
                          point: 3
                  comment_names:
                    - "良い点"
                    - "改善点"
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RubricCreateResponse'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationError'
        '500':
          $ref: '#/components/responses/ServerError'

  /rubric/{id}/edit:
    get:
      tags:
        - Views
      summary: ルーブリック編集フォーム表示
      description: 指定されたルーブリックの編集画面を表示します
      operationId: showEditForm
      parameters:
        - $ref: '#/components/parameters/RubricId'
      responses:
        '200':
          description: 成功
          content:
            text/html:
              schema:
                type: string
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'

  /rubric/{id}:
    put:
      tags:
        - Rubrics
      summary: ルーブリック更新
      description: 既存のルーブリックを更新します
      operationId: updateRubric
      parameters:
        - $ref: '#/components/parameters/RubricId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RubricUpdateRequest'
            examples:
              update:
                summary: 既存ルーブリックの更新
                value:
                  title: "情報リテラシー評価（更新版）"
                  description: "更新した説明"
                  attribute: "評価項目"
                  level: "優れている,良い,努力が必要"
                  categories:
                    - id: 1
                      title: "情報収集（更新）"
                    - title: "新しいカテゴリ"
                  criteria:
                    - id: 1
                      item: "情報の正確性（更新）"
                      category_id: 0
                      performances:
                        - id: 1
                          descriptor: "更新された記述"
                          point: 3
                        - descriptor: "新しい記述"
                          point: 2
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RubricUpdateResponse'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
        '500':
          $ref: '#/components/responses/ServerError'

    delete:
      tags:
        - Rubrics
      summary: ルーブリック削除
      description: 指定されたルーブリックを削除します
      operationId: deleteRubric
      parameters:
        - $ref: '#/components/parameters/RubricId'
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RubricDeleteResponse'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/ServerError'

  /rubric/{rubricId}/user/{userId}:
    get:
      tags:
        - Views
      summary: ユーザー評価表示
      description: 指定されたユーザーのルーブリック評価入力画面を表示します
      operationId: showUserEvaluation
      parameters:
        - name: rubricId
          in: path
          required: true
          schema:
            type: integer
          description: ルーブリックID
        - name: userId
          in: path
          required: true
          schema:
            type: integer
          description: ユーザーID
      responses:
        '200':
          description: 成功
          content:
            text/html:
              schema:
                type: string
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'

components:
  securitySchemes:
    cookieAuth:
      type: apiKey
      in: cookie
      name: laravel_session
    csrfToken:
      type: apiKey
      in: header
      name: X-CSRF-TOKEN

  parameters:
    RubricId:
      name: id
      in: path
      required: true
      schema:
        type: integer
      description: ルーブリックID

  schemas:
    RubricCreateRequest:
      type: object
      required:
        - title
        - attribute
        - level
        - criteria
      properties:
        title:
          type: string
          maxLength: 150
          description: ルーブリックのタイトル
          example: "情報リテラシー評価"
        description:
          type: string
          maxLength: 1000
          nullable: true
          description: ルーブリックの説明
          example: "情報リテラシーの評価ルーブリック"
        attribute:
          type: string
          maxLength: 50
          description: 評価項目の属性
          example: "評価項目"
        level:
          type: string
          maxLength: 250
          description: レベルラベル（カンマ区切り）
          example: "優れている,良い,努力が必要"
        rubric_criterion_id:
          type: integer
          nullable: true
          description: 親ルーブリックの観点ID
          example: null
        categories:
          type: array
          nullable: true
          description: カテゴリの配列
          items:
            $ref: '#/components/schemas/CategoryCreate'
        criteria:
          type: array
          minItems: 1
          description: 評価観点の配列
          items:
            $ref: '#/components/schemas/CriterionCreate'
        comment_names:
          type: array
          nullable: true
          description: 振り返りコメント名の配列
          items:
            type: string
            maxLength: 150
            example: "良い点"

    CategoryCreate:
      type: object
      required:
        - title
      properties:
        title:
          type: string
          maxLength: 150
          description: カテゴリ名
          example: "情報収集"

    CriterionCreate:
      type: object
      required:
        - item
        - performances
      properties:
        item:
          type: string
          maxLength: 250
          description: 評価項目名
          example: "情報の正確性"
        category_id:
          type: integer
          nullable: true
          description: カテゴリIDまたは配列インデックス
          example: 0
        performances:
          type: array
          minItems: 1
          description: パフォーマンス記述の配列
          items:
            $ref: '#/components/schemas/PerformanceCreate'

    PerformanceCreate:
      type: object
      required:
        - descriptor
        - point
      properties:
        descriptor:
          type: string
          maxLength: 1000
          description: パフォーマンス記述
          example: "信頼できる情報源から正確な情報を収集できる"
        point:
          type: integer
          description: 点数
          example: 3

    RubricUpdateRequest:
      allOf:
        - $ref: '#/components/schemas/RubricCreateRequest'
        - type: object
          properties:
            categories:
              type: array
              nullable: true
              items:
                $ref: '#/components/schemas/CategoryUpdate'
            criteria:
              type: array
              minItems: 1
              items:
                $ref: '#/components/schemas/CriterionUpdate'
            comment_names:
              type: array
              nullable: true
              items:
                $ref: '#/components/schemas/CommentNameUpdate'

    CategoryUpdate:
      type: object
      required:
        - title
      properties:
        id:
          type: integer
          nullable: true
          description: 既存カテゴリのID（更新時）
          example: 1
        title:
          type: string
          maxLength: 150
          description: カテゴリ名
          example: "情報収集"

    CriterionUpdate:
      type: object
      required:
        - item
        - performances
      properties:
        id:
          type: integer
          nullable: true
          description: 既存観点のID（更新時）
          example: 1
        item:
          type: string
          maxLength: 250
          description: 評価項目名
          example: "情報の正確性"
        category_id:
          type: integer
          nullable: true
          description: カテゴリIDまたは配列インデックス
          example: 0
        performances:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/PerformanceUpdate'

    PerformanceUpdate:
      type: object
      required:
        - descriptor
        - point
      properties:
        id:
          type: integer
          nullable: true
          description: 既存パフォーマンスのID（更新時）
          example: 1
        descriptor:
          type: string
          maxLength: 1000
          description: パフォーマンス記述
          example: "信頼できる情報源から正確な情報を収集できる"
        point:
          type: integer
          description: 点数
          example: 3

    CommentNameUpdate:
      type: object
      required:
        - title
      properties:
        id:
          type: integer
          nullable: true
          description: 既存コメント名のID（更新時）
          example: 1
        title:
          type: string
          maxLength: 150
          description: コメント名
          example: "良い点"

    RubricCreateResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        message:
          type: string
          example: "ルーブリックを作成しました"
        rubric_id:
          type: integer
          example: 1

    RubricUpdateResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        message:
          type: string
          example: "ルーブリックを更新しました"

    RubricDeleteResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        message:
          type: string
          example: "ルーブリックを削除しました"

    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        message:
          type: string
          example: "エラーが発生しました"

    ValidationErrorResponse:
      type: object
      properties:
        message:
          type: string
          example: "The given data was invalid."
        errors:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
          example:
            title:
              - "The title field is required."
            criteria.0.item:
              - "The criteria.0.item field is required."

  responses:
    Unauthorized:
      description: 認証が必要です
      content:
        text/html:
          schema:
            type: string

    Forbidden:
      description: 権限がありません
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            message: "指定された親観点にアクセスする権限がありません"

    NotFound:
      description: リソースが見つかりません
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'

    ValidationError:
      description: バリデーションエラー
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ValidationErrorResponse'

    ServerError:
      description: サーバーエラー
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            message: "ルーブリックの作成に失敗しました"
