"""
Example of how to use SimAuto methods in Python
Developed by PowerWorld 2019, created by Mayank Hirani

Retrieving and changing elements together
Includes: 
    OpenCase()
    GetParametersMultipleElement()
    ChangeParametersMultipleElement()
    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 Variant tools
from pythoncom import VT_VARIANT
from win32com.client import VARIANT

# 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 that will be used when retrieving the parameters and values, 
# as well as changing values
# VARIANT is a data type used for data processes, must be used here for the
# arrays of arrays.
parameters = VARIANT(VT_VARIANT, [ "BusNum", "GenID", "GenMW" ])

# Retrieve the numbers of the buses and their corresponding GenMW
(err, values) = SimAuto.GetParametersMultipleElement("Gen", parameters, "")
if err:
    raise Exception(f'Error: {err}')
else:
    print('Obtained current values')


# Array structure:
"""
[[BusNum_1, BusNum_2, ... BusNum_N]
 [GenID_1,  GenID_2,  ... GenID_N]
 [GenMW_1,  GenMW_2,  ... GenMW_N]]
"""

v_bus = [x.strip() for x in values[0]]
v_ids = [x.strip() for x in values[1]]
v_mws = [float(x.strip()) for x in values[2]]

# Print current values
print ('Current values:')
for i in range(len(v_bus)):
    print(f'({v_bus[i]}, {v_ids[i]}): {v_mws[i]} MW')
print()

# Calculate the average MW output
avg_mw = sum(v_mws)/len(v_mws)

# Make new value structure, setting the output of each
# generator to the average
new_vals = [VARIANT(VT_VARIANT, [v_bus[i], v_ids[i], avg_mw]) for i in range(len(v_bus))]

# Change the values using ChangeParametersMultipleElement() 
(err,) = SimAuto.ChangeParametersMultipleElement("Gen", parameters, new_vals)
if err:
    raise Exception(f'Error: {err}')
else:
    print(f'Changed all MW output to average ({avg_mw} MW)')

# Retrieve the numbers of the buses and their corresponding GenMW
(err, values) = SimAuto.GetParametersMultipleElement("Gen", parameters, "")
if err:
    raise Exception(f'Error: {err}')
else:
    print('Obtained updated values')

v_bus = [x.strip() for x in values[0]]
v_ids = [x.strip() for x in values[1]]
v_mws = [float(x.strip()) for x in values[2]]

# Print current values
print("Updated values:")
for i in range(len(v_bus)):
    print(f'({v_bus[i]}, {v_ids[i]}): {v_mws[i]} MW')
print()

# Close the case
(err,) = SimAuto.CloseCase()
if err:
    raise Exception(f'Error: {err}')
else:
    print("Closed Case")

# Disconnect
SimAuto = None
