"""
Example of how to use SimAuto methods in Python
Developed by PowerWorld 2019, created by Mayank Hirani

Query values from case, modify in Python, and re-load changes back to the case
Includes:
    OpenCase()
    GetParametersMultipleElementRect()
    ChangeParametersMultipleElementsRect()
    CloseCase()
"""

# Specify file path to test case
file_name = "C:\\Training Cases\\B7FLAT.pwb" # Set this to a path on your system

# Import file path tools
import os

# Import the win32com library to connect to SimAuto
import win32com.client
SimAuto = win32com.client.Dispatch("pwrworld.SimulatorAuto")

# Open the case using the file path
(err,) = SimAuto.OpenCase(file_name)
if err:
    raise Exception(f'Error: {err}')
else:
    print(f'Opened {os.path.basename(file_name)}')

# The fields to be used -- "BusNum" and "GenID" are primary
# key fields used to identify Generators
parameters = [ "BusNum", "GenID", "GenMW" ]

# Get the parameters using GetParametersMultipleElementRect(), 
# which returns the values for each bus as a tuple of tuples
(err, values) = SimAuto.GetParametersMultipleElementRect("Gen", parameters, "")
if err:
    raise Exception(f'Error: {err}')
else:
    print('Obtained current values')

# Output structure:
"""
[[BusNum_1, GenID_1, GenMW_1]
 [BusNum_2, GenID_2, GenMW_2]
    ...
 [BusNum_N, GenID_N, GenMW_N]]
"""

# Print current values
print ("Current values:")
for gen in values:
    print(f'({gen[0]}, {gen[1]}): {gen[2]} MW')
print()

# Calculate the average MW output
gen_mw = [float(x[2].strip()) for x in values]
avg_mw = sum(gen_mw)/len(gen_mw)

# Make new value structure, setting the output of each
# generator to the average
new_vals = [(gen[0],gen[1],avg_mw) for gen in values]

# Change the values using ChangeParametersMultipleElementRect()
(err,) = SimAuto.ChangeParametersMultipleElementRect("Gen", parameters, new_vals)
if err:
    raise Exception(f'Error: {err}')
else:
    print(f'Changed all MW output to average ({avg_mw} MW)')

# Check that the change was correctly applied
(err, values) = SimAuto.GetParametersMultipleElementRect("Gen", parameters, "")
if err:
    raise Exception(f'Error: {err}')
else:
    print('Obtained updated values')
    
# Print updated values
print ("Updated values:")
for gen in values:
    print(f'({gen[0]}, {gen[1]}): {gen[2]} MW')
print()

# Close the case
(err,) = SimAuto.CloseCase()
if err:
    raise Exception(f'Error: {err}')
else:
    print("Closed Case")

# Disconnect
SimAuto = None
