black and also set_language isn't "correct" anymore.

so it doesn't move the student on.

	modified:   app.py
	modified:   migrations/env.py
	modified:   migrations/versions/190d5ef26e20_add_token_count_to_message.py
	modified:   migrations/versions/a9e886c56482_create_room_table.py
	modified:   migrations/versions/d737de68d6fa_add_metadata_field_to_activitystate.py
	modified:   research/activity21.yaml
	modified:   research/guarded_ai.py
This commit is contained in:
Russell Ballestrini 2024-08-10 17:00:52 -04:00
parent 5f4cf76372
commit f5df195e9b
7 changed files with 187 additions and 117 deletions

28
app.py
View file

@ -2164,13 +2164,22 @@ def handle_activity_response(room_name, user_response, username):
for key, value in transition["metadata_add"].items():
if value == "the-users-response":
value = user_response
elif isinstance(value, str) and (value.startswith("n+") or value.startswith("n-")):
# Extract the numeric part c and apply the operation +/-
c = int(value[1:])
if value.startswith("n+"):
value = activity_state.dict_metadata.get(key, 0) + c
elif value.startswith("n-"):
value = activity_state.dict_metadata.get(key, 0) - c
elif isinstance(value, str):
if value.startswith("n+random(") and value.endswith(")"):
# Extract the range and apply the random increment
range_values = value[9:-1].split(",")
if len(range_values) == 2:
x, y = map(int, range_values)
value = activity_state.dict_metadata.get(
key, 0
) + random.randint(x, y)
elif value.startswith("n+") or value.startswith("n-"):
# Extract the numeric part c and apply the operation +/-
c = int(value[1:])
if value.startswith("n+"):
value = activity_state.dict_metadata.get(key, 0) + c
elif value.startswith("n-"):
value = activity_state.dict_metadata.get(key, 0) - c
new_metadata[key] = value
activity_state.add_metadata(key, value)
@ -2271,9 +2280,10 @@ def handle_activity_response(room_name, user_response, username):
if (
category
not in [
"off_topic",
"asking_clarifying_questions",
"partial_understanding",
"asking_clarifying_questions",
"set_language",
"off_topic",
]
or activity_state.attempts >= activity_state.max_attempts
):

View file

@ -12,32 +12,31 @@ config = context.config
# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)
logger = logging.getLogger('alembic.env')
logger = logging.getLogger("alembic.env")
def get_engine():
try:
# this works with Flask-SQLAlchemy<3 and Alchemical
return current_app.extensions['migrate'].db.get_engine()
return current_app.extensions["migrate"].db.get_engine()
except (TypeError, AttributeError):
# this works with Flask-SQLAlchemy>=3
return current_app.extensions['migrate'].db.engine
return current_app.extensions["migrate"].db.engine
def get_engine_url():
try:
return get_engine().url.render_as_string(hide_password=False).replace(
'%', '%%')
return get_engine().url.render_as_string(hide_password=False).replace("%", "%%")
except AttributeError:
return str(get_engine().url).replace('%', '%%')
return str(get_engine().url).replace("%", "%%")
# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
config.set_main_option('sqlalchemy.url', get_engine_url())
target_db = current_app.extensions['migrate'].db
config.set_main_option("sqlalchemy.url", get_engine_url())
target_db = current_app.extensions["migrate"].db
# other values from the config, defined by the needs of env.py,
# can be acquired:
@ -46,7 +45,7 @@ target_db = current_app.extensions['migrate'].db
def get_metadata():
if hasattr(target_db, 'metadatas'):
if hasattr(target_db, "metadatas"):
return target_db.metadatas[None]
return target_db.metadata
@ -64,9 +63,7 @@ def run_migrations_offline():
"""
url = config.get_main_option("sqlalchemy.url")
context.configure(
url=url, target_metadata=get_metadata(), literal_binds=True
)
context.configure(url=url, target_metadata=get_metadata(), literal_binds=True)
with context.begin_transaction():
context.run_migrations()
@ -84,13 +81,13 @@ def run_migrations_online():
# when there are no changes to the schema
# reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
def process_revision_directives(context, revision, directives):
if getattr(config.cmd_opts, 'autogenerate', False):
if getattr(config.cmd_opts, "autogenerate", False):
script = directives[0]
if script.upgrade_ops.is_empty():
directives[:] = []
logger.info('No changes in schema detected.')
logger.info("No changes in schema detected.")
conf_args = current_app.extensions['migrate'].configure_args
conf_args = current_app.extensions["migrate"].configure_args
if conf_args.get("process_revision_directives") is None:
conf_args["process_revision_directives"] = process_revision_directives
@ -98,9 +95,7 @@ def run_migrations_online():
with connectable.connect() as connection:
context.configure(
connection=connection,
target_metadata=get_metadata(),
**conf_args
connection=connection, target_metadata=get_metadata(), **conf_args
)
with context.begin_transaction():

View file

@ -11,17 +11,18 @@ import sqlalchemy as sa
from sqlalchemy.orm import Session
# revision identifiers, used by Alembic.
revision = '190d5ef26e20'
down_revision = 'a9e886c56482'
revision = "190d5ef26e20"
down_revision = "a9e886c56482"
branch_labels = None
depends_on = None
from app import Message
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('message', schema=None) as batch_op:
batch_op.add_column(sa.Column('token_count', sa.Integer(), nullable=True))
with op.batch_alter_table("message", schema=None) as batch_op:
batch_op.add_column(sa.Column("token_count", sa.Integer(), nullable=True))
# Use this binding to connect to the database
bind = op.get_bind()
@ -38,5 +39,5 @@ def upgrade():
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('message', schema=None) as batch_op:
batch_op.drop_column('token_count')
with op.batch_alter_table("message", schema=None) as batch_op:
batch_op.drop_column("token_count")

View file

@ -3,36 +3,36 @@ import sqlalchemy as sa
from sqlalchemy.sql import table, column, select
# revision identifiers, used by Alembic.
revision = 'a9e886c56482'
revision = "a9e886c56482"
down_revision = None
branch_labels = None
depends_on = None
def upgrade():
# Create room table
op.create_table('room',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('title', sa.String(length=128), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
op.create_table(
"room",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.String(length=128), nullable=False),
sa.Column("title", sa.String(length=128), nullable=True),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("name"),
)
# Add room_id column to message table
op.add_column('message', sa.Column('room_id', sa.Integer(), nullable=True))
op.add_column("message", sa.Column("room_id", sa.Integer(), nullable=True))
# Temporary table objects
message_table = table('message',
column('id', sa.Integer),
column('username', sa.String),
column('content', sa.String),
column('room', sa.String),
column('room_id', sa.Integer),
)
room_table = table('room',
column('id', sa.Integer),
column('name', sa.String)
message_table = table(
"message",
column("id", sa.Integer),
column("username", sa.String),
column("content", sa.String),
column("room", sa.String),
column("room_id", sa.Integer),
)
room_table = table("room", column("id", sa.Integer), column("name", sa.String))
# Execution context
conn = op.get_bind()
@ -40,74 +40,86 @@ def upgrade():
# Insert distinct rooms into room table and create mapping
distinct_rooms = conn.execute(select(message_table.c.room).distinct())
room_name_to_id = {}
for room_name, in distinct_rooms:
for (room_name,) in distinct_rooms:
conn.execute(room_table.insert().values(name=room_name))
room_id = conn.execute(select(room_table.c.id).where(room_table.c.name == room_name)).scalar()
room_id = conn.execute(
select(room_table.c.id).where(room_table.c.name == room_name)
).scalar()
room_name_to_id[room_name] = room_id
# Update message table with room_id
for room_name, room_id in room_name_to_id.items():
conn.execute(message_table.update().where(message_table.c.room == room_name).values(room_id=room_id))
conn.execute(
message_table.update()
.where(message_table.c.room == room_name)
.values(room_id=room_id)
)
# Create new_message table
new_message_table = op.create_table('new_message',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('username', sa.String(length=128), nullable=False),
sa.Column('content', sa.String(length=1024), nullable=False),
sa.Column('room_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['room_id'], ['room.id']),
sa.PrimaryKeyConstraint('id')
new_message_table = op.create_table(
"new_message",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("username", sa.String(length=128), nullable=False),
sa.Column("content", sa.String(length=1024), nullable=False),
sa.Column("room_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(["room_id"], ["room.id"]),
sa.PrimaryKeyConstraint("id"),
)
# Copy data from old message table to new_message table
old_messages = conn.execute(sa.select(message_table)).fetchall()
for old_message in old_messages:
conn.execute(new_message_table.insert().values(
id=old_message.id,
username=old_message.username,
content=old_message.content,
room_id=old_message.room_id
))
conn.execute(
new_message_table.insert().values(
id=old_message.id,
username=old_message.username,
content=old_message.content,
room_id=old_message.room_id,
)
)
# Drop old message table and rename new_message to message
op.drop_table('message')
op.rename_table('new_message', 'message')
op.drop_table("message")
op.rename_table("new_message", "message")
def downgrade():
# Recreate old_message table with 'room' column
old_message_table = op.create_table('old_message',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('username', sa.String(length=128), nullable=False),
sa.Column('content', sa.String(length=1024), nullable=False),
sa.Column('room', sa.String(length=128), nullable=False),
sa.PrimaryKeyConstraint('id')
old_message_table = op.create_table(
"old_message",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("username", sa.String(length=128), nullable=False),
sa.Column("content", sa.String(length=1024), nullable=False),
sa.Column("room", sa.String(length=128), nullable=False),
sa.PrimaryKeyConstraint("id"),
)
# Copy data back from message to old_message
message_table = table('message',
column('id', sa.Integer),
column('username', sa.String),
column('content', sa.String),
column('room_id', sa.Integer)
)
room_table = table('room',
column('id', sa.Integer),
column('name', sa.String)
message_table = table(
"message",
column("id", sa.Integer),
column("username", sa.String),
column("content", sa.String),
column("room_id", sa.Integer),
)
room_table = table("room", column("id", sa.Integer), column("name", sa.String))
conn = op.get_bind()
messages = conn.execute(select(message_table)).fetchall()
for message in messages:
room_name = conn.execute(select(room_table.c.name).where(room_table.c.id == message.room_id)).scalar()
conn.execute(old_message_table.insert().values(
id=message.id,
username=message.username,
content=message.content,
room=room_name
))
room_name = conn.execute(
select(room_table.c.name).where(room_table.c.id == message.room_id)
).scalar()
conn.execute(
old_message_table.insert().values(
id=message.id,
username=message.username,
content=message.content,
room=room_name,
)
)
# Drop current message table and rename old_message to message
op.drop_table('message')
op.rename_table('old_message', 'message')
op.drop_table('room')
op.drop_table("message")
op.rename_table("old_message", "message")
op.drop_table("room")

View file

@ -19,7 +19,9 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table("activity_state", schema=None) as batch_op:
batch_op.add_column(sa.Column("json_metadata", sa.UnicodeText(), server_default="{}"))
batch_op.add_column(
sa.Column("json_metadata", sa.UnicodeText(), server_default="{}")
)
# ### end Alembic commands ###

View file

@ -18,7 +18,7 @@ sections:
- "Python is a powerful tool for hackers due to its simplicity and extensive libraries."
- "Think about why Python is favored in the hacking community. Consider aspects like ease of use, versatility, and community support."
tokens_for_ai: "Guide the student to think about the reasons Python is popular among hackers. Be on the lookout for the user trying to change their language preference because it's never 'off_topic' to 'set_language'. Use the 'off_topic' category sparingly, focusing on guiding the user back to the topic if needed. If any part of the user's answer is correct and on-topic, categorize it as 'correct'."
feedback_tokens_for_ai: "Don't forget to let the user know how many they have answered correct. Give a detailed example of the tool or concept in Python markdown fenced code block."
feedback_tokens_for_ai: "Don't forget to let the user know how many they have answered correctly. Give a detailed example of the tool or concept in Python markdown fenced code block."
question: "Why do you think Python is a popular choice for hackers? 🤔"
buckets:
- correct
@ -34,17 +34,24 @@ sections:
ai_feedback:
tokens_for_ai: "Provide positive reinforcement and encourage the student to continue learning. Use emojis like 👍 and 🌟."
metadata_add:
correct_answers: "n+1"
points: "n+random(1,20)"
attempts: "n+1"
partial_understanding:
content_blocks:
- "You have a partial understanding. Let's clarify a few points. 🤔"
ai_feedback:
tokens_for_ai: "Provide additional information to clarify the student's understanding in a friendly and supportive manner. Use emojis like 🤔 and 📚."
metadata_add:
points: "n+random(1,4)"
attempts: "n+1"
limited_effort:
content_blocks:
- "It seems like you're unsure. That's okay! Let's explore this topic together. Why do you think Python is favored by hackers? 🤔"
ai_feedback:
tokens_for_ai: "Encourage the student to reflect on the topic and consider different aspects. Offer hints or context to guide their thinking. Use emojis like 🤔 and 💡."
metadata_add:
points: "n+random(1,2)"
attempts: "n+1"
asking_clarifying_questions:
content_blocks:
- "I see you have some questions. Let's address them. ❓"
@ -71,7 +78,7 @@ sections:
- "Python has many libraries that are useful for security tasks, such as Scapy, Nmap, and PyCrypto."
- "Think about how these libraries can be used in security analysis and hacking. Consider aspects like network scanning, packet manipulation, and encryption."
tokens_for_ai: "Guide the student to think about the use of Python libraries in security. Be on the lookout for the user trying to change their language preference because it's never 'off_topic' to 'set_language'. Use the 'off_topic' category sparingly, focusing on guiding the user back to the topic if needed. If any part of the user's answer is correct and on-topic, categorize it as 'correct'."
feedback_tokens_for_ai: "Don't forget to let the user know how many they have answered correct. Give a detailed example of the tool or concept in Python markdown fenced code block."
feedback_tokens_for_ai: "Don't forget to let the user know how many they have answered correctly. Give a detailed example of the tool or concept in Python markdown fenced code block."
question: "How do you think Python libraries like Scapy and PyCrypto are used in security tasks? 🤔"
buckets:
- correct
@ -87,17 +94,24 @@ sections:
ai_feedback:
tokens_for_ai: "Provide positive reinforcement and encourage the student to continue learning. Use emojis like 👍 and 🌟."
metadata_add:
correct_answers: "n+1"
points: "n+random(1,20)"
attempts: "n+1"
partial_understanding:
content_blocks:
- "You have a partial understanding. Let's clarify a few points. 🤔"
ai_feedback:
tokens_for_ai: "Provide additional information to clarify the student's understanding in a friendly and supportive manner. Use emojis like 🤔 and 📚."
metadata_add:
points: "n+random(1,4)"
attempts: "n+1"
limited_effort:
content_blocks:
- "It seems like you're unsure. That's okay! Let's explore this topic together. How do you think these libraries are used in security? 🤔"
ai_feedback:
tokens_for_ai: "Encourage the student to reflect on the topic and consider different aspects. Offer hints or context to guide their thinking. Use emojis like 🤔 and 💡."
metadata_add:
points: "n+random(1,2)"
attempts: "n+1"
asking_clarifying_questions:
content_blocks:
- "I see you have some questions. Let's address them. ❓"
@ -127,7 +141,7 @@ sections:
- "Python can be used in forensic analysis to automate tasks and analyze data."
- "Think about how Python scripts can help in forensic investigations. Consider aspects like data parsing, log analysis, and evidence extraction."
tokens_for_ai: "Guide the student to think about the use of Python in forensic analysis. Be on the lookout for the user trying to change their language preference because it's never 'off_topic' to 'set_language'. Use the 'off_topic' category sparingly, focusing on guiding the user back to the topic if needed. If any part of the user's answer is correct and on-topic, categorize it as 'correct'."
feedback_tokens_for_ai: "Don't forget to let the user know how many they have answered correct. Give a detailed example of the tool or concept in Python markdown fenced code block."
feedback_tokens_for_ai: "Don't forget to let the user know how many they have answered correctly. Give a detailed example of the tool or concept in Python markdown fenced code block."
question: "How do you think Python can be used in forensic analysis? 🤔"
buckets:
- correct
@ -143,17 +157,24 @@ sections:
ai_feedback:
tokens_for_ai: "Provide positive reinforcement and encourage the student to continue learning. Use emojis like 👍 and 🌟."
metadata_add:
correct_answers: "n+1"
points: "n+random(1,20)"
attempts: "n+1"
partial_understanding:
content_blocks:
- "You have a partial understanding. Let's clarify a few points. 🤔"
ai_feedback:
tokens_for_ai: "Provide additional information to clarify the student's understanding in a friendly and supportive manner. Use emojis like 🤔 and 📚."
metadata_add:
points: "n+random(1,4)"
attempts: "n+1"
limited_effort:
content_blocks:
- "It seems like you're unsure. That's okay! Let's explore this topic together. How do you think Python helps in forensic analysis? 🤔"
ai_feedback:
tokens_for_ai: "Encourage the student to reflect on the topic and consider different aspects. Offer hints or context to guide their thinking. Use emojis like 🤔 and 💡."
metadata_add:
points: "n+random(1,2)"
attempts: "n+1"
asking_clarifying_questions:
content_blocks:
- "I see you have some questions. Let's address them. ❓"
@ -180,7 +201,7 @@ sections:
- "Automation is key in forensic analysis to handle large volumes of data efficiently."
- "Think about how Python can automate repetitive tasks in forensic investigations. Consider aspects like script execution, data filtering, and report generation."
tokens_for_ai: "Guide the student to think about automating forensic tasks with Python. Be on the lookout for the user trying to change their language preference because it's never 'off_topic' to 'set_language'. Use the 'off_topic' category sparingly, focusing on guiding the user back to the topic if needed. If any part of the user's answer is correct and on-topic, categorize it as 'correct'."
feedback_tokens_for_ai: "Don't forget to let the user know how many they have answered correct. Give a detailed example of the tool or concept in Python markdown fenced code block."
feedback_tokens_for_ai: "Don't forget to let the user know how many they have answered correctly. Give a detailed example of the tool or concept in Python markdown fenced code block."
question: "How do you think Python can automate tasks in forensic investigations? 🤔"
buckets:
- correct
@ -196,17 +217,24 @@ sections:
ai_feedback:
tokens_for_ai: "Provide positive reinforcement and encourage the student to continue learning. Use emojis like 👍 and 🌟."
metadata_add:
correct_answers: "n+1"
points: "n+random(1,20)"
attempts: "n+1"
partial_understanding:
content_blocks:
- "You have a partial understanding. Let's clarify a few points. 🤔"
ai_feedback:
tokens_for_ai: "Provide additional information to clarify the student's understanding in a friendly and supportive manner. Use emojis like 🤔 and 📚."
metadata_add:
points: "n+random(1,4)"
attempts: "n+1"
limited_effort:
content_blocks:
- "It seems like you're unsure. That's okay! Let's explore this topic together. How do you think Python automates forensic tasks? 🤔"
ai_feedback:
tokens_for_ai: "Encourage the student to reflect on the topic and consider different aspects. Offer hints or context to guide their thinking. Use emojis like 🤔 and 💡."
metadata_add:
points: "n+random(1,2)"
attempts: "n+1"
asking_clarifying_questions:
content_blocks:
- "I see you have some questions. Let's address them. ❓"
@ -236,7 +264,7 @@ sections:
- "Python is used in security engineering to develop tools and scripts for vulnerability assessment and penetration testing."
- "Think about how Python can be used to identify and exploit vulnerabilities. Consider aspects like script development, tool integration, and testing automation."
tokens_for_ai: "Guide the student to think about the use of Python in security engineering. Be on the lookout for the user trying to change their language preference because it's never 'off_topic' to 'set_language'. Use the 'off_topic' category sparingly, focusing on guiding the user back to the topic if needed. If any part of the user's answer is correct and on-topic, categorize it as 'correct'."
feedback_tokens_for_ai: "Don't forget to let the user know how many they have answered correct. Give a detailed example of the tool or concept in Python markdown fenced code block."
feedback_tokens_for_ai: "Don't forget to let the user know how many they have answered correctly. Give a detailed example of the tool or concept in Python markdown fenced code block."
question: "How do you think Python is used in security engineering? 🤔"
buckets:
- correct
@ -252,17 +280,24 @@ sections:
ai_feedback:
tokens_for_ai: "Provide positive reinforcement and encourage the student to continue learning. Use emojis like 👍 and 🌟."
metadata_add:
correct_answers: "n+1"
points: "n+random(1,20)"
attempts: "n+1"
partial_understanding:
content_blocks:
- "You have a partial understanding. Let's clarify a few points. 🤔"
ai_feedback:
tokens_for_ai: "Provide additional information to clarify the student's understanding in a friendly and supportive manner. Use emojis like 🤔 and 📚."
metadata_add:
points: "n+random(1,4)"
attempts: "n+1"
limited_effort:
content_blocks:
- "It seems like you're unsure. That's okay! Let's explore this topic together. How do you think Python is used in security engineering? 🤔"
ai_feedback:
tokens_for_ai: "Encourage the student to reflect on the topic and consider different aspects. Offer hints or context to guide their thinking. Use emojis like 🤔 and 💡."
metadata_add:
points: "n+random(1,2)"
attempts: "n+1"
asking_clarifying_questions:
content_blocks:
- "I see you have some questions. Let's address them. ❓"
@ -289,7 +324,7 @@ sections:
- "Python is often used to develop custom security tools for specific tasks."
- "Think about how you can use Python to create tools for security analysis. Consider aspects like functionality, user interface, and integration with other tools."
tokens_for_ai: "Guide the student to think about developing security tools with Python. Be on the lookout for the user trying to change their language preference because it's never 'off_topic' to 'set_language'. Use the 'off_topic' category sparingly, focusing on guiding the user back to the topic if needed. If any part of the user's answer is correct and on-topic, categorize it as 'correct'."
feedback_tokens_for_ai: "Don't forget to let the user know how many they have answered correct. Give a detailed example of the tool or concept in Python markdown fenced code block."
feedback_tokens_for_ai: "Don't forget to let the user know how many they have answered correctly. Give a detailed example of the tool or concept in Python markdown fenced code block."
question: "How do you think you can use Python to develop security tools? 🤔"
buckets:
- correct
@ -305,17 +340,24 @@ sections:
ai_feedback:
tokens_for_ai: "Provide positive reinforcement and encourage the student to continue learning. Use emojis like 👍 and 🌟."
metadata_add:
correct_answers: "n+1"
points: "n+random(1,20)"
attempts: "n+1"
partial_understanding:
content_blocks:
- "You have a partial understanding. Let's clarify a few points. 🤔"
ai_feedback:
tokens_for_ai: "Provide additional information to clarify the student's understanding in a friendly and supportive manner. Use emojis like 🤔 and 📚."
metadata_add:
points: "n+random(1,4)"
attempts: "n+1"
limited_effort:
content_blocks:
- "It seems like you're unsure. That's okay! Let's explore this topic together. How do you think Python can be used to develop security tools? 🤔"
ai_feedback:
tokens_for_ai: "Encourage the student to reflect on the topic and consider different aspects. Offer hints or context to guide their thinking. Use emojis like 🤔 and 💡."
metadata_add:
points: "n+random(1,2)"
attempts: "n+1"
asking_clarifying_questions:
content_blocks:
- "I see you have some questions. Let's address them. ❓"

View file

@ -226,13 +226,20 @@ def simulate_activity(yaml_file_path):
for key, value in transition["metadata_add"].items():
if value == "the-users-response":
value = user_response
elif isinstance(value, str) and (value.startswith("n+") or value.startswith("n-")):
# Extract the numeric part c and apply the operation +/-
c = int(value[1:])
if value.startswith("n+"):
value = metadata.get(key, 0) + c
elif value.startswith("n-"):
value = metadata.get(key, 0) - c
elif isinstance(value, str):
if value.startswith("n+random(") and value.endswith(")"):
# Extract the range and apply the random increment
range_values = value[9:-1].split(",")
if len(range_values) == 2:
x, y = map(int, range_values)
value = metadata.get(key, 0) + random.randint(x, y)
elif value.startswith("n+") or value.startswith("n-"):
# Extract the numeric part c and apply the operation +/-
c = int(value[1:])
if value.startswith("n+"):
value = metadata.get(key, 0) + c
elif value.startswith("n-"):
value = metadata.get(key, 0) - c
metadata[key] = value
if "metadata_tmp_add" in transition:
@ -264,9 +271,10 @@ def simulate_activity(yaml_file_path):
print(f"\nMetadata: {json.dumps(metadata, indent=2)}")
if category not in [
"off_topic",
"asking_clarifying_questions",
"partial_understanding",
"asking_clarifying_questions",
"set_language",
"off_topic",
]:
break