Documentation of API functions

API for providing company and product details

inserting_attributes(Company, Product, Attributes) async

Please provide your company's name, product and its attributes.

Example of attributes format: ["Attribute1", "Attribute2", "Attribute3"]

Parameters:
  • Company (str) –

    Name of the company

  • Product (str) –

    Name of the product

  • Attributes (list[str]) –

    List of attributes characterizing the product

Returns:
  • str

    Clarification

Source code in BWS\api\api_company_details.py
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@app.post("/Provide Company Details/{Company}&{Product}")
async def inserting_attributes(Company: str, Product: str, Attributes: list[str]):
    """
    Please provide your company's name, product and its attributes.

    Example of attributes format: ["Attribute1", "Attribute2", "Attribute3"]

    Args:
        Company (str): Name of the company
        Product (str): Name of the product
        Attributes (list[str]): List of attributes characterizing the product

    Returns:
        str: Clarification
    """
    column_name = f"{Company}__{Product}"
    inst.insert_attributes(column_name, Attributes)
    return {"Data inserted successfully"}

API for conducting (answering) the survey

get_current_task() async

Retrieve attributes for the current task and allow users to select best and worst attributes.

Raises:
  • HTTPException

    description

  • HTTPException

    description

  • HTTPException

    description

  • HTTPException

    description

Returns:
  • _type_

    description

Source code in BWS\api\api_part2.py
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
@app.get("/block/tasks", response_model=dict)
async def get_current_task():
    """
    Retrieve attributes for the current task and allow users to select best and worst attributes.

    Raises:
        HTTPException: _description_
        HTTPException: _description_
        HTTPException: _description_
        HTTPException: _description_

    Returns:
        _type_: _description_
    """
    global current_task, last_task_id, task_attributes_entered

    if current_task > 10:
        return {"message": "Thank you for your feedback!"}

    # Retrieve respondent's ID and block from stored information
    Respondent_ID = respondent_info.get("user")
    block = ((Respondent_ID - 1) % 10) + 1

    if not Respondent_ID:
        raise HTTPException(status_code=400, detail="User ID not provided")

    # Check if task attributes have been entered and accepted, skip this check for the first task
    if current_task > 1 and not task_attributes_entered:
        # Check if the last task ID is set
        if last_task_id is None:
            raise HTTPException(status_code=400, detail="No task selected. Please retrieve a task using the GET endpoint first.")

        # Retrieve attributes for the last task from the survey table based on the block
        row = instance.get_row_from_survey("survey_Apple__Iphone", last_task_id - 1, block)  # Index is 0-based
        if not row:
            raise HTTPException(status_code=404, detail=f"No attributes found for Task {last_task_id} and Block {block}")

        # Extract attributes from the row
        attributes = row[2:]

        # Prepare response with message and last task's attributes
        response1 = {
            "message": "Please enter and submit the current task's attributes before proceeding to the next task.",
            "current_task_attributes": attributes
        }

        return response1

    # Retrieve attributes for the current task from the survey table based on the block
    row = instance.get_row_from_survey("survey_Apple__Iphone", current_task - 1, block)  # Index is 0-based
    if not row:
        raise HTTPException(status_code=404, detail=f"No attributes found for Task {current_task} and Block {block}")

    # Extract attributes from the row
    attributes = row[2:]

    # Prepare response with task ID and attributes
    response2 = {
        "task_id": current_task,
        "attributes": attributes
    }

    # Store the current task ID as the last task ID
    last_task_id = current_task

    # Automatically move to the next task for the next request
    current_task += 1

    # Reset the flag for task attributes entered and accepted
    task_attributes_entered = False

    return response2

select_age_range(Age_Range=Query(..., description='Please select your age range from the options provided above')) async

Please select your age range: - Under 18: <18, - 18-25: 18-25, - 26-35: 26-35, - 36-45: 36-45, - Above 45: >45

Parameters:
  • Age_Range (str, default: Query(..., description='Please select your age range from the options provided above') ) –

    description. Defaults to Query(..., description="Please select your age range from the options provided above").

Raises:
  • HTTPException

    description

  • HTTPException

    description

Returns:
  • dict

    Clarification

Source code in BWS\api\api_part2.py
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
@app.post("/Demographics/Age_Range", response_model=dict)
async def select_age_range(Age_Range: str = Query(..., description="Please select your age range from the options provided above")):
    """
    Please select your age range:
    - Under 18: <18,
    - 18-25: 18-25,
    - 26-35: 26-35,
    - 36-45: 36-45,
    - Above 45: >45

    Args:
        Age_Range (str, optional): _description_. Defaults to Query(..., description="Please select your age range from the options provided above").

    Raises:
        HTTPException: _description_
        HTTPException: _description_

    Returns:
        dict: Clarification
    """
    global demographics_changed

    if demographics_changed:
        raise HTTPException(status_code=400, detail="Please complete all tasks in the current block before changing demographics.")

    if Age_Range not in age_ranges.values():
        raise HTTPException(status_code=400, detail="Invalid age range selected")

    # Store respondent's age range
    respondent_info["age_range"] = Age_Range

    # Create the response table if it does not exist
    instance.create_response_table(table_name=table)  

    # Check if the response table is empty
    if instance.is_table_empty(table_name=table):
        # If the table is empty, assign the first respondent ID as 1
        respondent_info["user"] = 1
    else:
        # If the table is not empty, get the last respondent ID from the table and assign the next respondent ID
        last_respondent_ID = instance.get_last_respondent_ID(table)
        respondent_info["user"] = last_respondent_ID + 1

    # Reset the flag for changing demographics
    demographics_changed = False

    return {"message": "Age range saved successfully"}

select_gender(Gender=Query(..., description='Please select your gender')) async

Gender: - Female - Male

Parameters:
  • Gender (str, default: Query(..., description='Please select your gender') ) –

    description. Defaults to Query(..., description="Please select your gender").

Raises:
  • HTTPException

    description

  • HTTPException

    description

Returns:
  • dict

    Clarification

Source code in BWS\api\api_part2.py
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
@app.post("/demographics/gender", response_model=dict)
async def select_gender(Gender: str = Query(..., description="Please select your gender")):
    """
    Gender:
    - Female
    - Male

    Args:
        Gender (str, optional): _description_. Defaults to Query(..., description="Please select your gender").

    Raises:
        HTTPException: _description_
        HTTPException: _description_

    Returns:
        dict: Clarification
    """
    global demographics_changed

    if demographics_changed:
        raise HTTPException(status_code=400, detail="Please complete all tasks in the current block before changing demographics.")

    if Gender.lower() not in gender_options:
        raise HTTPException(status_code=400, detail="Invalid gender selected")

    # Store respondent's gender
    respondent_info["gender"] = Gender.lower()

    # Set the flag indicating demographics have been changed
    demographics_changed = True

    return {"message": "Gender saved successfully"}

select_task_attributes(best_attribute=Query(...), worst_attribute=Query(...)) async

Allow users to select best and worst attributes for the current task.

Parameters:
  • best_attribute (str, default: Query(...) ) –

    description. Defaults to Query(...).

  • worst_attribute (str, default: Query(...) ) –

    description. Defaults to Query(...).

Raises:
  • HTTPException

    description

  • HTTPException

    description

  • HTTPException

    description

  • HTTPException

    description

  • HTTPException

    description

Returns:
  • dict

    Dictionary containing the best and worst selected attributes by the user

Source code in BWS\api\api_part2.py
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
@app.post("/block/tasks/selection", response_model=dict)
async def select_task_attributes(best_attribute: str = Query(...), worst_attribute: str = Query(...)):
    """
    Allow users to select best and worst attributes for the current task.

    Args:
        best_attribute (str, optional): _description_. Defaults to Query(...).
        worst_attribute (str, optional): _description_. Defaults to Query(...).

    Raises:
        HTTPException: _description_
        HTTPException: _description_
        HTTPException: _description_
        HTTPException: _description_
        HTTPException: _description_

    Returns:
        dict: Dictionary containing the best and worst selected attributes by the user
    """
    global last_task_id, task_attributes_entered

    Respondent_ID = respondent_info.get("user")
    if not Respondent_ID:
        raise HTTPException(status_code=400, detail="User ID not provided")

    # Calculate block based on user ID
    block = ((Respondent_ID - 1) % 10) + 1

    Age_Range = respondent_info.get("age_range")
    Gender = respondent_info.get("gender")

    # Check if last_task_id is None, indicating that no GET request has been made yet
    if last_task_id is None:
        raise HTTPException(status_code=400, detail="No task selected. Please retrieve a task using the GET endpoint first.")

    # Retrieve attributes for the specified task from the survey table
    row = instance.get_row_from_survey("survey_Apple__Iphone", last_task_id - 1, block)  # Index is 0-based
    if not row:
        raise HTTPException(status_code=404, detail=f"No attributes found for Task {last_task_id}")

    # Extract attributes from the row
    available_attributes = row[2:]

    # Check if the selected attributes are available for the task
    if best_attribute not in available_attributes or worst_attribute not in available_attributes:
        raise HTTPException(status_code=400, detail=f"Invalid attribute selection. Task {last_task_id} does not have the selected attribute(s)")

    # Store the selected best and worst attributes, along with Respondent_ID, age range, gender, and block in the database
    try:
        instance.store_response(table_name=table, Respondent_ID=Respondent_ID, Block=block, Task=last_task_id, Attributes=available_attributes, Best_Attribute=best_attribute, Worst_Attribute=worst_attribute, Age_Range=Age_Range, Gender=Gender)
    except Exception as e:
        raise HTTPException(status_code=500, detail="Failed to store attribute response")

    # Set the flag indicating task attributes have been entered and accepted
    task_attributes_entered = True

    return {"best_attribute": best_attribute, "worst_attribute": worst_attribute}

API for serving the conducted analysis

get_product_analysis(company_name, product_name)

Function for serving the analysis to the product owners

Parameters:
  • company_name (str) –

    Name of the company

  • product_name (str) –

    Name of the product

Returns:
  • dict

    Message clarification of the endpoint

Source code in BWS\api\api_part3.py
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@app.get("/analysis")
def get_product_analysis(company_name: str, product_name: str):
    """
    Function for serving the analysis to the product owners

    Args:
        company_name (str): Name of the company
        product_name (str): Name of the product

    Returns:
        dict: Message clarification of the endpoint
    """    
    sql_handler = SqlHandle()  # Assuming this initializes your database connection
    table_names = [f"analysis{i}_{company_name}__{product_name}" for i in range(1, 4)]
    results = {}

    for table_name in table_names:
        try:
            df = sql_handler.read_table(table_name)
            if df is not None:
                results[table_name] = df.to_dict(orient="records")
            else:
                results[table_name] = None
        except Exception as e:
            results[table_name] = str(e)

    return results

update_product(company, old_product, new_product) async

Endpoint to update the product name in the Attributes table.

Parameters:
  • company (str) –

    Company Name

  • old_product (str) –

    Old Product Name

  • new_product (str) –

    New Product Name

Raises:
  • HTTPException

    description

Returns:
  • dict

    Message of the updata

Source code in BWS\api\api_update.py
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@app.put("/update_product_name/{company}/{old_product}")
async def update_product(company: str, old_product: str, new_product: str):
    """
    Endpoint to update the product name in the Attributes table.

    Args:
        company (str): Company Name
        old_product (str): Old Product Name
        new_product (str): New Product Name

    Raises:
        HTTPException: _description_

    Returns:
        dict: Message of the updata
    """
    # Call the function to update the product name
    result = instance.update_product_name(company, old_product, new_product)
    if "successfully" in result.lower():
        return {"message": result}
    else:
        raise HTTPException(status_code=404, detail=result)