"""
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()
    GetParametersMultipleElementFlatOutput()
    ChangeParametersMultipleElementsFlatInput()
    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)}')

# Specify fields
param_list = ['BusNum', 'BusPUVolt']

print()
values = SimAuto.GetParametersMultipleElementFlatOutput('BUS', param_list, '')
"""
values structure:
[err, N, #params, BusNum_1, BusPUVolt_1, BusNum_2, BusPUVolt_2, ... BusNum_N, BusPUVolt_N]
"""
err = values[0]
n = int(values[1]) # number of objects returned
p = int(values[2]) # number of fields per object
buses = values[3:] # The data itself

if err:
    raise Exception(f'Error: {err}')
else:
    print ('Current values:')
    busnums = [] # Collect BusNums to build new value list
    for i in range(n):
        print(f'({buses[p*i]}): {buses[p*i+1]} pu')
        busnums.append(buses[p*i])
    print()

# creating val_list
vals_new = []
for busnum in busnums:
    vals_new.extend([busnum, 1])

"""
vals_new structure:
[BusNum_1, BusPUVolt_1, BusNum_2, BusPUVolt_2, ... BusNum_N, BusPUVolt_N]
"""

# apply new values
(err,) = SimAuto.ChangeParametersMultipleElementFlatInput('BUS', param_list, len(busnums), vals_new)
if err:
    raise Exception(f'Error: {err}')
else:
    print("Applied changes")
print()

# Print new values
values = SimAuto.GetParametersMultipleElementFlatOutput('BUS', param_list, '')

err = values[0] # Error message
n = int(values[1]) # number of objects returned
p = int(values[2]) # number of fields per object
buses = values[3:]

if err:
    raise Exception(f'Error: {err}')
else:
    print("New values:")    
    for i in range(n):
        print(f'({buses[p*i]}): {buses[p*i+1]} pu')
    print()

# Close the case
(err,) = SimAuto.CloseCase()
if err:
    raise Exception(f'Error: {err}')
else:
    print("Closed Case")
    
# Disconnect
SimAuto = None
